Go语言使用httputil实现反向代理返回404错误如何解决
问题分析
- 路由匹配规则冲突:Go 标准库的
http.ServeMux对路由路径严格区分末尾斜杠,你源站注册的路由是/run,而代理默认转发后的路径是/run/(带末尾斜杠),无法匹配到注册的处理函数,因此返回404。 - 反向代理路径拼接逻辑不符合预期:
httputil.NewSingleHostReverseProxy默认会将客户端请求的路径直接追加到目标URL的路径之后,你初始化时传入的目标URL路径为/run/,如果要所有请求都固定转发到/run,默认拼接逻辑无法满足需求。
修复方案
方案1:固定所有代理请求转发到源站/run路径(适配当前代码需求)
直接修改反向代理的Director函数,重写转发路径和Host头,修正后的代理代码如下:
package main import ( "log" "net/http" "net/http/httputil" "net/url" ) func main() { demoUrl, err := url.Parse("http://localhost:1000") if err != nil { log.Fatal(err) return } proxy := httputil.NewSingleHostReverseProxy(demoUrl) // 覆盖默认的Director逻辑 originalDirector := proxy.Director proxy.Director = func(r *http.Request) { originalDirector(r) // 强制指定转发路径为/run,忽略客户端请求的路径 r.URL.Path = "/run" // 修正Host头,避免源站做Host校验时不通过 r.Host = demoUrl.Host } http.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) { proxy.ServeHTTP(rw, r) }) log.Println("代理服务启动,监听端口:2000") _ = http.ListenAndServe(":2000", nil) }
修改后访问http://localhost:2000即可正常拿到源站返回的I am running内容。
方案2:保留默认路径拼接逻辑
如果你希望代理路径和源站路径对应,比如访问代理http://localhost:2000/run转发到源站http://localhost:1000/run,可以做以下修改:
- 初始化反向代理的目标URL改为根路径:
url.Parse("http://localhost:1000") - 调整代理路由规则与源站路由保持一致即可,也可以直接将源站路由注册为
/run/,适配带末尾斜杠的路径请求。
内容的提问来源于stack exchange,提问作者Ritik Jain
相关产品推荐
相关产品推荐

