Golang HTTP Post错误:连接被拒绝

时间:2015-02-06 23:16:57

标签: post go

我正在尝试向运行PHP应用程序的端口8080上的localhost发送post请求。

卷曲工作正常:

curl --data "key=asdf" http://localhost:8080/

但在Go中我收到以下错误:

Post http://localhost:8080: dial tcp 127.0.0.1:8080: connection refused

以下是代码:

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")

我使用httpry监控http流量,我发现没有生成http请求,但有一些软件包:

4 packets received, 0 packets dropped, 0 http packets parsed

更多事实:

  • 我的操作系统是Linux
  • 我使用PHP的内置Web服务器。使用此命令启动服务器:

    php -S localhost:8080

1 个答案:

答案 0 :(得分:9)

此问题似乎已在Go 1.6中得到解决。作为参考,原始答案如下。

这里的问题是Go的net.Dialer默认只生成IPv4连接(这似乎是一个bug),但是你的PHP服务器只在IPv6上监听

当您运行php -S localhost:8080时,它正在执行(大部分)正确的操作并绑定到IPv6地址::1。它不绑定到IPv4。

对于knows to attempt IPv6 connections first的大多数软件来说,这不是问题,但是当你调用http.PostForm()时会发生什么,net.http使用它的DefaultTransport,默认使用net.Dialer {3}}拨号()以建立传出连接。 Dial()尝试解析地址,然后我们在src / net / ipsock.go中的解析器中找到 deep ,在那里我们发现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.

这显然是一个问题,因为IPv6应该是默认和首选协议。 Linux和PHP表现正常,而Go本身则不然。

以上评论见于1.4分支。在主分支中,这已被完全重写,但在新代码中,不优选IPv6或IPv4地址是否是首选。它可能是不确定的;我没有花太多时间看它。基于我在GitHub上发现的问题(见下文),它不太可能实际修复。

与此同时,您可以通过Go连接到::1或将PHP绑定到127.0.0.1来解决此错误。你也可以用正确的行为构建你自己的RoundTripper,但这可能太多了,除非你实际上遇到了启用IPv6服务的问题(最终我们都会这样做,所以这真的需要修复)。

一些相关的Go问题包括:

由于代码早已被重写,其他几个不再相关的旧问题......