Request via IPv6 ip result in a broken Host header

This is a regression from 2.7.0 and 2.9.1.  When using a URL with an IPv6 ip in the host part of the url:
http://[2620:10d:c021:11::75]/foo, in 2.7.0 the Host header looks correct as so: 
Host: [2620:10d:c021:11::75]
But when using 2.9.1, it gets munged:
Host: [[2620:10d:c021:11::75]]
This causes Django to barf.


Just to clarify, where did you install requests from?


So this was probably introduced by shazow/urllib3#708. Looks like we'll have to revert that @shazow.

@pneumaticdeath Why Python version are you using?


I got it from https://pypi.python.org/packages/source/r/requests/requests-2.9.1.tar.gz#md5=0b7f480d19012ec52bab78292efd976d


lol if only we had a better comment on that line, maybe this time...


I've tried in both python 2.7.9, and in python 3.3.x (don't remember right now which version)


Yup, so that's why we need an explanation for the logic. I'll fix it up tomorrow if no one beats me to it. 


Ugh, typically while I found that [this bug](https://bugs.python.org/issue5111) 'fixed' the issue I didn't look any closer than that. It does fix the issue, but in the most naive way possible, meaning that of course it does not fix it at all.

Goddamn I hate httplib sometimes.


And in fact my previous example was not good enough. This is what I've found so far:

``` python
Python 3.4.3 (default, Sep 15 2015, 12:08:21) 
[GCC 4.2.1 Compatible Apple LLVM 6.1.0 (clang-602.0.53)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import http.client
>>> c = http.client.HTTPConnection('[2001:0:53aa:64c:104c:2c10:2bef:4f7b]')
>>> c = http.client.HTTPConnection('2001:0:53aa:64c:104c:2c10:2bef:4f7b')
Traceback (most recent call last):
  File "/Users/cory/.pyenv/versions/3.4.3/lib/python3.4/http/client.py", line 786, in _get_hostport
    port = int(host[i+1:])
ValueError: invalid literal for int() with base 10: '4f7b'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/cory/.pyenv/versions/3.4.3/lib/python3.4/http/client.py", line 750, in __init__
    (self.host, self.port) = self._get_hostport(host, port)
  File "/Users/cory/.pyenv/versions/3.4.3/lib/python3.4/http/client.py", line 791, in _get_hostport
    raise InvalidURL("nonnumeric port: '%s'" % host[i+1:])
http.client.InvalidURL: nonnumeric port: '4f7b'
```

But also

```
>>> c = http.client.HTTPConnection('::1', 8000)
>>> c.request('GET', '/')
>>> c = http.client.HTTPConnection('[::1]', 8000)
>>> c.request('GET', '/')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/cory/.pyenv/versions/3.5.1/lib/python3.5/http/client.py", line 1083, in request
    self._send_request(method, url, body, headers)
  File "/Users/cory/.pyenv/versions/3.5.1/lib/python3.5/http/client.py", line 1128, in _send_request
    self.endheaders(body)
  File "/Users/cory/.pyenv/versions/3.5.1/lib/python3.5/http/client.py", line 1079, in endheaders
    self._send_output(message_body)
  File "/Users/cory/.pyenv/versions/3.5.1/lib/python3.5/http/client.py", line 911, in _send_output
    self.send(msg)
  File "/Users/cory/.pyenv/versions/3.5.1/lib/python3.5/http/client.py", line 854, in send
    self.connect()
  File "/Users/cory/.pyenv/versions/3.5.1/lib/python3.5/http/client.py", line 826, in connect
    (self.host,self.port), self.timeout, self.source_address)
  File "/Users/cory/.pyenv/versions/3.5.1/lib/python3.5/socket.py", line 693, in create_connection
    for res in getaddrinfo(host, port, 0, SOCK_STREAM):
  File "/Users/cory/.pyenv/versions/3.5.1/lib/python3.5/socket.py", line 732, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno 8] nodename nor servname provided, or not known
```

What this appears to mean is that in some cases the square brackets are mandatory, and in some cases they're optional. I'm so far not capable of getting the Host header to be wrong though, so I don't fully understand how that's happening


httplib/http.client seems to just be making a total hash of this. I don't understand at all. And that causes us a problem, because we can't revert the change unconditionally without breaking shazow/urllib3#707. So now everything is sad and terrible.


AHA! This isn't a urllib3 bug per se, it's a requests bug. That is, the example used in urllib3 in the original bug was fixed, we just do something different in requests.

Thank goodness, I thought I was losing my mind.


Ah, no, it's all terrible again: urllib3 gets this wrong if you use a poolmanager instead of `connection_from_url`. So we're back to urllib3 again.


Ok, so the summary here is that the original fix is bad. Rather than removing that strip, we needed to fix `connection_from_url`.

Ok, good, well now we have a plan of action at least.


So @shazow: the problem we have here is that the connection_from_url would not pass the port explicitly. That's avoided with the pool manager (which in `connection_from_host` defaults the port appropriately) and it's avoided in requests because it uses pool manager's `connection_from_url` which _also_ defaults the port.

I think this suggests a good fix.


Ok, a proposed fix is in shazow/urllib3#801.


Silly github auto-closed this issue, re-opened.


I'm pretty impressed it did that :)


I'm a little disappointed it did that.


I'm assuming it was because all collaborators were involved. I've never seen that happen before. 


Is there any plan to release a new version of the request library that contains the fixed urllib3?

The urllib3 1.15 has been released on 6 April 2016: https://pypi.python.org/pypi/urllib3

If need be, I can perhaps help with a PR to make this happen.


There is, yes. =) The next release of Requests will contain that update.


Ah, thank you. Is there any possible timeframe? This is so I can plan my work around this.

Also would the next release be backward compatible?

It seems there's this PR #2431 marked for next release that would break backward compatibility.


The next release will be backward compatible because it won't be 3.0.0, it'll be 2.X.


I know I might be stretching it - any time frame? This is so I can plan my work around this.


We have no explicit time frame, but Kenneth has been wanting to release for a while so I'd expect it to be soon.


Ok, thank you @Lukasa !


Hopefully this week :)


Thanks @kennethreitz!