为了让 API 连接正常工作,我需要在请求头中提供客户端 ID,基于用户名或客户端证书,然后将流量重定向到它。听起来像是专用反向代理软件 Nginx 或 Traefik 要执行的任务。现在我们来探索用 Golang 来实现反向代理的功能。
单主机反向代理
得益于 Golang 标准库,一个开箱即用的单主机反向代理可以很容易地实现。
1 | rp := httputil.NewSingleHostReverseProxy(targetUrl) |
这段代码应该插入标准的 HTTP 处理程序中。这里的“单一主机”更多指的是反向代理功能,没有提供负载均衡功能。
携带 header 的反向代理
这里会实现一个 HTTP 处理程序,读取客户端证书,并根据 CN 名称选择一个客户端 ID 值,在 HTTP 头部中更新它,并将流量重定向到目标 URL。
给出以下示例配置。
1 | mapping: |
1 | func main() { |
我们使用带有证书和密钥的基 于HTTPs 的服务器。请注意 TLS 选项,我们将要求客户端提供其证书以提取其 CN 名称,尽管我们不执行mTLS。
可以通过以下方式实现http处理程序:
1 | func rpHandler(mapping []CnToClientID, targetUrl *url.URL) func(w http.ResponseWriter, r *http.Request) { |
在处理程序中,首先我们读取客户端证书以获取其 CN 名称,然后循环遍历配置以找到客户端 ID 值,将其添加到请求头中,然后创建一个反向代理对象,目标 URL 是让它处理该请求。
自定义 Round Trip
我们需要一些自定义来解决反向代理的问题,可能需要跳过证书验证,因为目标端可能使用自签名证书。
这些可以通过 RoundTrip 的接口实现。
RoundTripper是一个接口,代表着执行单个HTTP事务的能力,获取给定请求的响应。
1 | type MyRoundTripper struct{} |
在 Roundtrip()
中,我们调用 httputil.DumpRequest
来为了调试目的而转储请求。
然后重置其 TLS
配置以跳过证书验证,以允许自签名证书通过。然后我们调用原始的 RoundTrip()
来处理请求。
然后可以使用自定义的 roundtrip
更新 http
处理程序。
1 | ... |