Golang HTTP Post错误:连接被拒绝 [英] Golang HTTP Post error: connection refused

查看:911
本文介绍了Golang HTTP Post错误:连接被拒绝的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



卷曲工作正常:
我试图在PHP端口8080上发送一个posthost请求到本地主机。

  curl --datakey = asdfhttp:// localhost:8080 / 

但是在Go中出现以下错误:

 发布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个数据包,丢弃0个数据包,解析0个http数据包

更多事实:


  • 我的操作系统是Linux

  • 我使用PHP的内置Web服务器。服务器是用这个命令启动的:
    $ b $ p


解决方案

这个问题似乎在Go 1.6中得到了解决。 拨号程序仅默认使用IPv4连接(这似乎是一个错误),但您的PHP服务器仅在IPv6上监听。



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



这对于大多数软件来说都不是问题,它们知道先尝试IPv6连接,但是当你调用http.PostForm()时会发生什么,net.http使用它的 DefaultTransport ,它默认使用 net.Dialer 拨号()进行传出连接。 Dial()尝试解析地址,然后我们在src / net / ipsock.go中的解析器中结束 deep ,在那里我们发现Go开发人员在尝试工作时故意搞砸了它

  //我们将取任何IP地址,但由于拨号
//代码尚未尝试使用多个地址
//,如果
//可能,则更愿意使用IPv4地址。如果localhost
//解析为[ipv6-localhost,ipv4-localhost],这尤其相关。太多
//很多代码假设localhost == ipv4-localhost。

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



上面的注释在1.4分支中找到。在主分支中,这已被完全重写,但在新代码中,IPv6或IPv4地址是否优先是不明显的。这可能是不确定的;我没有花太多时间看它。根据我在GitHub上发现的问题(见下文),它不太可能被修复。



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



一些相关的Go问题包括:



还有其他一些旧问题不再相关,因为代码早已被重写......

I am trying to send a post request to localhost on port 8080 where a PHP app is running.

Curl work fine:

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

But in Go I get the following error:

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

Here is the code:

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

I monitored http traffic with httpry and i found out that no http request is generated but there are some packages:

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

Some more facts:

  • My OS is Linux
  • I use the PHP's built-in web server. The servers was started with this command:

    php -S localhost:8080

解决方案

This issue appears to be resolved in Go 1.6. For reference, the original answer follows.


The problem here is that Go's net.Dialer only makes IPv4 connections by default (this appears to be a bug), but your PHP server is listening only on IPv6.

When you run php -S localhost:8080 it is doing the (mostly) right thing and binding to the IPv6 address ::1. It does not bind to IPv4.

This isn't a problem for most software, which knows to attempt IPv6 connections first, but what happens when you call http.PostForm() is that net.http uses its DefaultTransport, which by default uses a net.Dialer Dial() to make outgoing connections. Dial() attempts to resolve the address, and then we wind up deep in the resolver in src/net/ipsock.go, where we find out that the Go developers intentionally screwed it up while trying to work around something else:

        // 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.

This is obviously a problem, since IPv6 is supposed to be the default and preferred protocol. Linux and PHP are behaving correctly, while Go itself is not.

The comment above was found in the 1.4 branch. In the master branch this has been completely rewritten, but in the new code it's non-obvious whether an IPv6 or IPv4 address will be preferred. It may well be nondeterministic; I didn't spend too much time looking at it. Based on the issues I found on GitHub, (see below) it is unlikely to be actually fixed.

In the meantime you can work around this bug by either having Go connect to ::1 or having PHP bind to 127.0.0.1. You could also construct your own RoundTripper with correct behavior, but that's probably too much work, unless you're actually having problems reaching IPv6-enabled services (and eventually we all will, so this really needs to be fixed).

Some relevant Go issues include:

And several other older issues that are no longer relevant since the code has long since been rewritten...

这篇关于Golang HTTP Post错误:连接被拒绝的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆