-
Notifications
You must be signed in to change notification settings - Fork 18k
net/http: Transport does not handle 302 redirects with link-local server address correctly #20669
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Where is this behavior defined in a spec? That 302 response's Location header is |
/cc @mikioh |
It seems to me, there are no RFCs concerning this behaviour. Web server just use requst's HOST-header, we've send to it, in response's Location-header, it has no idea about zones, because they're local to client. It is client, who should decide, how to reach specified location. |
I don't want to complicate Go's code for a niche use case that's not even defined. |
But it just does not work now: strange exception after correct http-server response... It's weird. Modern curl, for example, deals with that kind of addresses in responses easily. |
Curl is probably not handling it and just handling connection cache management differently and you're getting lucky. If you find evidence that curl is explicitly handling this in some way, then I might be convinced to do the same. Please go grep the curl source code and figure out whether curl deals with IPv6 zones. |
See https://tools.ietf.org/html/rfc6874. Handling "beyond routing scope" is one of classic IPv6 issues and that's the reason why IPv6 site-local unicast addresses are deprecated: https://tools.ietf.org/html/rfc3879. So using IPv6 literals in HTTP has some restriction. I'm guessing that one control plane solution could be the combo of a) using mDNS for propagating on-link adjacency information and b) using non-IPv6 literals, node/service names propagated by mDNS, in HTTP. |
fe80::1 is not kind of site-local, but a link-local address – they will not be deprecated in the near future for sure :). It is like an 192.168.0.1 in ipv4 world, because of a common pattern to set it on |
@max2k1, I think you messed up your quoting there. I'm not sure how to read that comment. Somebody needs to translate this into English for me. I speak a little networking, but not as a native language. |
Curl does recognise different scopes of ip6-addresses here: https://github.com/curl/curl/blob/93567071b744975e191c5732d9cbe4b0d529f4c9/lib/if2ip.c#L69-L76 |
See https://tools.ietf.org/html/rfc6874#section-4. RFC 3879 describes the rest of pains on operating "scope boundaries."
Nope, see https://tools.ietf.org/html/rfc3927. The equivalent of IPv4 private addresses is https://tools.ietf.org/html/rfc4193. |
Sorry, I'll try to be simpler. |
And why doesn't it work now? Per RFC 6874, we already remove the zone identifier from the outgoing Host header: https://github.com/golang/go/blob/release-branch.go1.8/src/net/http/request.go#L678 That was added in 957255f and has tests. So we already can successfully make requests to http://[fe80::1%whatever]:80. But what says that when that server replies with a redirect code + Location header response without a zone, which zone are we supposed to use? |
We know local interface of this tcp-connection. So this is zone id. |
Okay, I think I finally understand what you want. In the future, please write your bug report with all the information. I would consider a patch for this if it's minimally invasive, but I don't intend to work on this myself. |
I have no strong opinion on this feature because I have no measurement for IPv6 addressing/routing scope boundary handling in transport- and/or session-layer protocols, such as HTTP. FWIW, the net/http package provides the |
Change https://golang.org/cl/64911 mentions this issue: |
This looks like an undefined behavior of HTTP, so I think supporting this explicitly is not necessary. cURL extracts zone ID from link-local address and store them separately. cURL uses both of them to setup connections and use address as key to cache connections. So the second request sent by cURL uses the previous connection and can send request successfully. Python doesn't handle zone ID at all. The relevant cURL code is I think using the same logic(do not use zone ID in cache key) in Go is enough. |
Please answer these questions before submitting your issue. Thanks!
What version of Go are you using (
go version
)?What operating system and processor architecture are you using (
go env
)?What did you do?
I need to get some data from link-local neighbor:
What did you expect to see?
Something like this:
What did you see instead?
Get http://[fe80::1]:8002/info.sh: dial tcp [fe80::1]:8002: connect: invalid argument
It happened, because
http://[fe80::1%eth0]:8002/info.json
returned 302-redirect to /info.sh and http-library lost zone-prefix somewhere while following redirect.Proof:
The text was updated successfully, but these errors were encountered: