I have a simple Go proxy like so. I want to proxy requests through to it and modify the responses of certain websites. These websites run over TLS, but my proxy is just a local server.
func main() {
target, _ := url.Parse("https://www.google.com")
proxy := httputil.NewSingleHostReverseProxy(target)
proxy.ModifyResponse = rewriteBody
http.Handle("/", proxy)
http.ListenAndServe(":80", proxy)
}
Result: 404 error as shown in the following screenshot:
From my understanding, the proxy server would initiate the request and close the request, then return the response after modification. I'm not sure what would fail here. Am I missing something w.r.t to forwarding headers to where this request is failing?
Edit
I've gotten the routing working. Originally, I was interested in modifying the response, but not seeing any change except I see the Magical
header.
func modifyResponse() func(*http.Response) error {
return func(resp *http.Response) error {
resp.Header.Set("X-Proxy", "Magical")
b, _ := ioutil.ReadAll(resp.Body)
b = bytes.Replace(b, []byte("About"), []byte("Modified String Test"), -1) // replace html
body := ioutil.NopCloser(bytes.NewReader(b))
resp.Body = body
resp.ContentLength = int64(len(b))
resp.Header.Set("Content-Length", strconv.Itoa(len(b)))
resp.Body.Close()
return nil
}
}
func main() {
target, _ := url.Parse("https://www.google.com")
proxy := httputil.NewSingleHostReverseProxy(target)
director := proxy.Director
proxy.Director = func(r *http.Request) {
director(r)
r.Host = r.URL.Hostname()
}
proxy.ModifyResponse = modifyResponse()
http.Handle("/", proxy)
http.ListenAndServe(":80", proxy)
}
CodePudding user response:
The critical problem is mentioned in the documentation, but it's not clear from the documentation how to deal with it exactly:
NewSingleHostReverseProxy does not rewrite the Host header. To rewrite Host headers, use ReverseProxy directly with a custom Director policy.
https://pkg.go.dev/net/http/httputil#NewSingleHostReverseProxy
You don't have the use ReverseProxy
directly. You can still use NewSingleHostReverseProxy
and adapt the Director
function like this:
func main() {
target, _ := url.Parse("https://www.google.com")
proxy := httputil.NewSingleHostReverseProxy(target)
director := proxy.Director
proxy.Director = func(r *http.Request) {
director(r)
r.Host = r.URL.Hostname() // Adjust Host
}
http.Handle("/", proxy)
http.ListenAndServe(":80", proxy)
}