func()

in openwhisk/forward_proxy.go [38:120]


func (ap *ActionProxy) ForwardRunRequest(w http.ResponseWriter, r *http.Request) {
	if ap.clientProxyData == nil {
		sendError(w, http.StatusInternalServerError, "Send init first")
		return
	}
	var runRequest runRequest
	err := json.NewDecoder(r.Body).Decode(&runRequest)
	if err != nil {
		sendError(w, http.StatusBadRequest, fmt.Sprintf("Error decoding run body while forwarding request: %v", err))
		return
	}

	newBody := runRequest
	newBody.ActionCodeHash = ap.clientProxyData.ActionCodeHash

	var buf bytes.Buffer
	err = json.NewEncoder(&buf).Encode(newBody)
	if err != nil {
		sendError(w, http.StatusBadRequest, fmt.Sprintf("Error encoding updated init body: %v", err))
		return
	}

	bodyLen := buf.Len()
	r.Body = io.NopCloser(bytes.NewBuffer(buf.Bytes()))

	director := func(req *http.Request) {
		req.Header = r.Header.Clone()

		// Reset content length with the new body
		req.Header.Set("Content-Length", strconv.Itoa(bodyLen))
		req.ContentLength = int64(bodyLen)

		req.URL.Scheme = ap.clientProxyData.ProxyURL.Scheme
		req.URL.Host = ap.clientProxyData.ProxyURL.Host
		req.Host = ap.clientProxyData.ProxyURL.Host
	}

	proxy := &httputil.ReverseProxy{Director: director}
	proxy.ErrorHandler = func(w http.ResponseWriter, r *http.Request, err error) {
		Debug("Error forwarding run request: %v", err)
		sendError(w, http.StatusBadGateway, "Error forwarding run request. Check logs for details.")
	}

	proxy.ModifyResponse = func(response *http.Response) error {
		if response.StatusCode == http.StatusOK {
			// Decode the response
			var remoteReponse RemoteRunResponse
			err := json.NewDecoder(response.Body).Decode(&remoteReponse)
			if err != nil {
				Debug("Error decoding remote response: %v", err)
				return err
			}

			// Write the logs to the client logs.
			if _, err := ap.outFile.WriteString(remoteReponse.Out); err != nil {
				Debug("Error writing remote response out to client: %v", err)
			}
			// Avoid spamming just the output guard if there is no error string
			if remoteReponse.Err != OutputGuard {
				if _, err := ap.errFile.WriteString(remoteReponse.Err); err != nil {
					Debug("Error writing remote response err to client: %v", err)
				}
			}

			// Keep the response body only
			response.Body = io.NopCloser(bytes.NewReader(remoteReponse.Response))

			// recalculate the content length
			response.ContentLength = int64(len(remoteReponse.Response))
			response.Header.Set("Content-Length", strconv.Itoa(len(remoteReponse.Response)))
		} else {
			Debug("Remote response status code: %d", response.StatusCode)
		}

		return nil
	}

	Debug("Forwarding run request with to %s", ap.clientProxyData.ProxyURL.String())
	proxy.ServeHTTP(w, r)
	if f, ok := w.(http.Flusher); ok {
		f.Flush()
	}
}