了解在路由时出现的Go代理失败情况

huangapple go评论89阅读模式
英文:

Understand Go proxy failures when routing

问题

我有一个简单的Go代理,像这样。我想通过代理将请求转发到它,并修改某些网站的响应。这些网站在TLS上运行,但我的代理只是一个本地服务器。

func main() {
	target, _ := url.Parse("https://www.google.com")

	proxy := httputil.NewSingleHostReverseProxy(target)
	proxy.ModifyResponse = rewriteBody

	http.Handle("/", proxy)
	http.ListenAndServe(":80", proxy)
}

结果:404错误,如下图所示:
了解在路由时出现的Go代理失败情况

根据我的理解,代理服务器会发起请求并关闭请求,然后在修改后返回响应。我不确定这里会出现什么问题。关于转发标头,我是否遗漏了一些内容?

编辑

我已经使路由工作正常。最初,我对修改响应感兴趣,但除了看到Magical标头外,没有看到任何变化。

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)
}
英文:

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:
了解在路由时出现的Go代理失败情况

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

答案1

得分: 1

关键问题在文档中提到,但从文档中并不清楚如何确切处理它:

> NewSingleHostReverseProxy不会重写Host标头。要重写Host标头,请直接使用ReverseProxy并使用自定义的Director策略。

https://pkg.go.dev/net/http/httputil#NewSingleHostReverseProxy

您不必直接使用ReverseProxy。您仍然可以使用NewSingleHostReverseProxy并调整Director函数,如下所示:

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() // 调整Host
    }
    http.Handle("/", proxy)
    http.ListenAndServe(":80", proxy)
}

希望对您有所帮助!

英文:

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

huangapple
  • 本文由 发表于 2023年1月7日 11:23:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/75037907.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定