我正在尝试通过工作代理发出http / s请求。
我在节点JS的旧项目中有一个工作示例,其中与以下选项对象一起使用时,使用本机Node.js https
(require('https')
)lib可以发出请求:
{
host: "<actual target url>"
hostname: "<proxy ip>"
}
例如,要通过代理example.com
向1.1.1.1
发出https请求,我将使用:
{
host: "http://example.com"
hostname: "1.1.1.1"
}
在Golang中,我尝试了一些记录在案的选项。 具体来说,我希望:
proxyUrl, _ := url.Parse("<proxy ip>")
myClient := &http.Client{Transport: &http.Transport{Proxy: http.ProxyURL(proxyUrl)}}
resp, err := myClient.Get("https://<actual target url>/...")
结果是代理拒绝连接,表明请求中有错误。 (err
存在,而resp是nil
)
代理本身是根据以下要点配置的NGINX实例:
https://gist.github.com/selfish/6e858eb17aa82971d25b21775e9649cb#file-nginx-conf
谁能帮助理解Node.js和Golang在HTTP处理方面的区别?
答案 0 :(得分:1)
您混淆了正向和反向代理。
从概念上讲,它是这样的:
反向代理
转发代理
(当然,现实要复杂得多,但这足以突出差异)。
Internet || Invisible to
+ || User Agent
| ||
+------------+ +---------------+ | +---------------+ || +--------+
| | | | | | | || | |
| User Agent +---->+ Forward Proxy +-------->+ Reverse Proxy +----->+ Origin |
| | | | | | | || | |
+------------+ +---------------+ | +---------------+ || +--------+
| ||
+ ||
||
nginx是反向代理,但是通过设置Transport.Proxy字段,您可以将其视为正向代理。这是nginx看到的请求:
CONNECT example.com:443 HTTP/1.1
Host: example.com:443
User-Agent: Go-http-client/1.1
这个基本含义是:“建立到example.com:443的TCP连接,然后像一个愚蠢的TCP代理一样工作。”由于nginx是反向代理,因此只有在遇到CONNECT请求时,它才是正确的混淆。
要将请求发送到特定的反向代理,您只需修改请求URL,并可能修改主机标头(取决于nginx是否期望特定的server_name
)。不需要特殊的客户端配置。
假设nginx在198.51.100.1
上运行:
req, _ := http.NewRequest("GET", "http://198.51.100.1", nil)
req.Host = "example.com" // if necessary
res, _ := http.DefaultClient.Do(req)
这将导致以下请求发送到198.51.100.1:80:
GET / HTTP/1.1
Host: example.com
User-Agent: Go-http-client/1.1
Accept-Encoding: gzip
请注意,如果请求确实到达了example.com,则完全取决于反向代理。客户对代理之后发生的事情一无所知或无法控制。
如果您无权更改请求,则可以设置Transport.DialContext函数,以便始终拨打代理,而与请求URL和主机标头无关。这将导致与上述请求相同的请求,并且应等同于您的JavaScript代码:
c := &http.Client{
Transport: &http.Transport{
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
return (&net.Dialer{}).DialContext(ctx, "tcp", "198.51.100.1:80")
// Or 198.51.100.1:443 if nginx has TLS enabled, although that almost
// certainly causes TLS validation errors because a certificate for
// example.com is expected.
},
},
}
req, _ := http.NewRequest("GET", "http://example.com", nil)
res, _ := c.Do(req)