Home > database >  Understand Go proxy failures when routing
Understand Go proxy failures when routing

Time:01-07

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: enter image description here

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)
}
  • Related