我正在为我的后端构建一个反向代理,但我不明白为什么即使我用文档中看到的任何方法更改主机头,它也不会更改. 后端需要真正的主持人才能提供正确的内容.

以下是代码:

proxy := &httputil.ReverseProxy{
    Director: func(req *http.Request) {
        targetURL := url.URL{
            Scheme: "http",
            Host:   "backend.com",
            Path:   req.URL.Path,
        }

        req.URL.Scheme = targetURL.Scheme
        req.URL.Host = targetURL.Host
        req.URL.Path = targetURL.Path
        req.Header.Set("Host", targetURL.Host)

    },
    Transport: transport,
}

// Listen on a local port and serve the reverse proxy without buffer method
server := &http.Server{
    Addr:    "localhost:8080",
    Handler: proxy,
}
fmt.Println("Listening on :8080...")
err = server.ListenAndServe()
if err != nil {
    fmt.Println(err)
}

推荐答案

如果你可以使用go1.20中添加的(*ProxyRequest).SetURL,就会很容易:

proxy := &httputil.ReverseProxy{
    Rewrite: func(pr *httputil.ProxyRequest) {
        targetURL := url.URL{
            Scheme: "http",
            Host:   "backend.com",
            Path:   req.URL.Path,
        }
        pr.SetURL(&targetURL)
    },
    Transport: transport,
}

有关更多信息,请参阅此提案:net/http/httputil: replace Director with Rewrite.


在不可能升级到Go 1.20的情况下,这里有一个适用于Director的解决方案:

  proxy := &httputil.ReverseProxy{
    Director: func(req *http.Request) {
        targetURL := url.URL{
            Scheme: "http",
            Host:   "backend.com",
            Path:   req.URL.Path,
        }

        req.URL.Scheme = targetURL.Scheme
        req.URL.Host = targetURL.Host
        req.URL.Path = targetURL.Path
-       req.Header.Set("Host", targetURL.Host)
+       req.Host = targetURL.Host
+       // or simply:
+       // req.Host = ""
    },
    Transport: transport,
  }

请参阅文档,了解http.Request.Host:

对于客户端请求,主机可以 Select 覆盖要发送的主机标头.如果为空,则Request.Wite方法使用URL.Host值.

Go相关问答推荐

SEARCH On Conflict Clause不考虑乐观锁定版本

如何模拟嵌入. FS?

在Go中根据命名空间/字符串生成UUID

如何在GoFr中为生产和本地环境设置不同的配置?

如何在gofr发起的服务间调用请求中添加Authorization Header?

在多个 struct 体中重用 Go 中的函数

git ls-remote 成功而 go get 失败

我的神经网络(从头开始)训练,让它离目标更远

没有任务角色的 AWS CDK ECS 任务定义

GOLANG:为什么 SetDeadline/SetReadDeadline/SetWriteDeadline 在使用 os.File.Fd() 时对文件不起作用?

Wire google Inject with multi return from provider 函数

获取切片元素的地址是否意味着 Go 中元素的副本?

grpc-gateway:重定向与定义不匹配(原始文件)

如何在 helm 中将字符串连接到 .AsConfig 的结果?

处理程序后访问 HTTP 请求上下文

函数超时和 goroutine 泄漏

如何在 golang 中同时加载 .env 文件和 os 环境变量

在 GORM 中,如何在特定时区配置 autoCreateTime 和 autoUpdateTime?

从 map 返回空数组而不是空字符串数组

并发 map map导致的 Golang 数据竞争