我正在尝试向运行PHP应用程序的端口8080上的localhost发送一个post请求.
卷曲工作正常:
curl --data "key=asdf" http://localhost:8080/
Run Code Online (Sandbox Code Playgroud)
但在Go中我收到以下错误:
Post http://localhost:8080: dial tcp 127.0.0.1:8080: connection refused
Run Code Online (Sandbox Code Playgroud)
这是代码:
func submitForm(value string){
resp, err := http.PostForm("http://localhost:8080", url.Values{"key": {value}})
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
_, err = ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println("status = ",resp.Status)
}
submitForm("asdf")
Run Code Online (Sandbox Code Playgroud)
我使用httpry监控http流量,我发现没有生成http请求,但有一些包:
4 packets received, 0 packets dropped, 0 http packets parsed
Run Code Online (Sandbox Code Playgroud)
更多事实:
我使用PHP的内置Web服务器.使用此命令启动服务器:
php -S localhost:8080
此问题似乎在Go 1.6中得到解决.作为参考,原始答案如下.
这里的问题是Go的net.Dialer默认只生成IPv4连接(这似乎是一个bug),但是你的PHP服务器只能监听IPv6.
当你运行php -S localhost:8080
它时,正在做(大多数)正确的事情并绑定到IPv6地址::1
.它不绑定到IPv4.
这对于大多数知道首先尝试IPv6连接的软件来说都不是问题,但是当你调用http.PostForm()时会发生什么,net.http使用它的DefaultTransport,默认情况下使用net.Dialer Dial()来建立传出连接.Dial()尝试解析地址,然后我们深入了解src/net/ipsock.go中的解析器,在那里我们发现Go开发人员在尝试解决其他问题时故意搞砸了:
// We'll take any IP address, but since the dialing
// code does not yet try multiple addresses
// effectively, prefer to use an IPv4 address if
// possible. This is especially relevant if localhost
// resolves to [ipv6-localhost, ipv4-localhost]. Too
// much code assumes localhost == ipv4-localhost.
Run Code Online (Sandbox Code Playgroud)
这显然是一个问题,因为IPv6应该是默认和首选协议.Linux和PHP表现正常,而Go本身则不然.
以上评论见于1.4分支.在主分支中,这已被完全重写,但在新代码中,不优选IPv6或IPv4地址是否是首选.它可能是不确定的; 我没有花太多时间看它.基于我在GitHub上发现的问题(见下文),它不太可能实际修复.
在此期间,您可以通过Go连接::1
或PHP绑定来解决此错误127.0.0.1
.您也可以使用正确的行为构建自己的RoundTripper,但这可能太多了,除非您实际上遇到了启用IPv6服务的问题(最终我们都会这样做,所以这确实需要修复).
一些相关的Go问题包括:
还有其他几个不再相关的旧问题,因为代码早已被重写......
归档时间: |
|
查看次数: |
17640 次 |
最近记录: |