How to build an http reverse proxy to dynamically change the content of the upstream response?

I’m thinking about creating something like this.

proxy := &httputil.ReverseProxy{
	Director:  director,
	Transport: &proxyTransport{},
}

server := http.Server{
	Addr:    ":6060",
	Handler: proxy,
}
server.ListenAndServe()

And the function func director(r *http.Request){} will change the URL of the request and the custom http.Transport will get the body of the upstream response, does the necessary modifications and sends down a new response.

func director(r *http.Request){
  r.URL = url.Parse("foo.bar")
}

.

type proxyTransport struct {
}

func (p *proxyTransport) RoundTrip(req *http.Request) (*http.Response, error) {
  res, err := trans.RoundTrip(req)
  if err != nil {
    return nil, err
  }

  body, err := httputil.DumpResponse(res, true)
  if err != nil {
    return nil, err
  }

 nbody := &bytes.Buffer{}
 nbody.Write(append(body, []byte("foo")...))
 b := ioutil.NopCloser(nbody)

  nres := &http.Response{
	StatusCode: http.StatusOK,
	Status:     fmt.Sprintf("%d %s", http.StatusOK, http.StatusText(http.StatusOK)),
	Proto:      "HTTP/1.1",
	ProtoMajor: 1,
	ProtoMinor: 1,
	Header:     http.Header{},
	Body:       b,
	Request:    req,
  }
  nres.Body.Close()
  return nres, nil
}

Is this the correct way to go? What other things I need to take care of to not to screw up the performance?

Perhaps better for performance is to implement a Reader that modifies the data before it’s written to the buffer, so that you don’t have to read the whole response body in memory at once.

This for example willl read something before and after the reader you are wrapping: https://play.golang.org/p/edl1V8Ft6H

If you want to modify the body itself, you probably have to load it all in memory anyway.

PS: in making your Response you don’t need to set some fields, like the protocol and the status twice. You are also discarding all the received response headers.

3 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.