Skip to content
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

Bracket IPv6 addresses in the HOST header (#3304) #3305

Merged
merged 2 commits into from
Oct 4, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES/3304.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Bracket IPv6 addresses in the HOST header
1 change: 1 addition & 0 deletions CONTRIBUTORS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ Paulius Šileikis
Paulus Schoutsen
Pavel Kamaev
Pawel Miech
Pavel Polyakov
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is out of order. T U V W X Y Z

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch!
Fixed by f6b81b3

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad, sorry

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably need to lint that :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think linux sort can be used for this.
For example, the check might look like LC_ALL=C sort -c CONTRIBUTORS.txt
But first you need to make it sorted: LC_ALL=C sort -o CONTRIBUTORS.txt CONTRIBUTORS.txt

First line may be changed as - Contributors for keep sorting

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't care too much -- but if somebody want to make a PR for this you are welcome

Pepe Osca
Philipp A.
Pieter van Beek
Expand Down
2 changes: 2 additions & 0 deletions aiohttp/client_reqrep.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,8 @@ def update_auto_headers(self, skip_auto_headers):
# add host
if hdrs.HOST not in used_headers:
netloc = self.url.raw_host
if helpers.is_ipv6_address(netloc):
netloc = '[{}]'.format(netloc)
if not self.url.is_default_port():
netloc += ':' + str(self.url.port)
self.headers[hdrs.HOST] = netloc
Expand Down
27 changes: 16 additions & 11 deletions aiohttp/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
from pathlib import Path
from types import TracebackType
from typing import (TYPE_CHECKING, Any, Callable, Dict, Iterable, Iterator,
List, Mapping, Optional, Tuple, Type, TypeVar, Union, cast)
List, Mapping, Optional, Pattern, Tuple, Type, TypeVar,
Union, cast)
from urllib.parse import quote
from urllib.request import getproxies

Expand Down Expand Up @@ -604,25 +605,29 @@ def __set__(self, inst: Any, value: Any) -> None:
_ipv6_regexb = re.compile(_ipv6_pattern.encode('ascii'), flags=re.IGNORECASE)


def is_ip_address(
host: Optional[Union[str, bytes, bytearray, memoryview]]) -> bool:
def _is_ip_address(
regex: Pattern, regexb: Pattern,
host: Optional[Union[str, bytes, bytearray, memoryview]])-> bool:
if host is None:
return False
if isinstance(host, str):
if _ipv4_regex.match(host) or _ipv6_regex.match(host):
return True
else:
return False
return bool(regex.match(host))
elif isinstance(host, (bytes, bytearray, memoryview)):
if _ipv4_regexb.match(host) or _ipv6_regexb.match(host): # type: ignore # noqa
return True
else:
return False
return bool(regexb.match(host))
else:
raise TypeError("{} [{}] is not a str or bytes"
.format(host, type(host)))


is_ipv4_address = functools.partial(_is_ip_address, _ipv4_regex, _ipv4_regexb)
is_ipv6_address = functools.partial(_is_ip_address, _ipv6_regex, _ipv6_regexb)


def is_ip_address(
host: Optional[Union[str, bytes, bytearray, memoryview]]) -> bool:
return is_ipv4_address(host) or is_ipv6_address(host)


_cached_current_datetime = None
_cached_formatted_datetime = None

Expand Down
20 changes: 20 additions & 0 deletions tests/test_client_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,26 @@ def test_host_header_explicit_host_with_port(make_request) -> None:
assert req.headers['HOST'] == 'example.com:99'


def test_host_header_ipv4(make_request) -> None:
req = make_request('get', 'http://127.0.0.2')
assert req.headers['HOST'] == '127.0.0.2'


def test_host_header_ipv6(make_request) -> None:
req = make_request('get', 'http://[::2]')
assert req.headers['HOST'] == '[::2]'


def test_host_header_ipv4_with_port(make_request) -> None:
req = make_request('get', 'http://127.0.0.2:99')
assert req.headers['HOST'] == '127.0.0.2:99'


def test_host_header_ipv6_with_port(make_request) -> None:
req = make_request('get', 'http://[::2]:99')
assert req.headers['HOST'] == '[::2]:99'


def test_default_loop(loop) -> None:
asyncio.set_event_loop(loop)
req = ClientRequest('get', URL('http://python.org/'))
Expand Down
13 changes: 12 additions & 1 deletion tests/test_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -390,11 +390,20 @@ def test_is_ip_address_bytes() -> None:
assert not helpers.is_ip_address(b"1200::AB00:1234::2552:7777:1313")


def test_ip_addresses() -> None:
def test_ipv4_addresses() -> None:
ip_addresses = [
'0.0.0.0',
'127.0.0.1',
'255.255.255.255',
]
for address in ip_addresses:
assert helpers.is_ipv4_address(address)
assert not helpers.is_ipv6_address(address)
assert helpers.is_ip_address(address)


def test_ipv6_addresses() -> None:
ip_addresses = [
'0:0:0:0:0:0:0:0',
'FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF',
'00AB:0002:3008:8CFD:00AB:0002:3008:8CFD',
Expand All @@ -405,6 +414,8 @@ def test_ip_addresses() -> None:
'1::1',
]
for address in ip_addresses:
assert not helpers.is_ipv4_address(address)
assert helpers.is_ipv6_address(address)
assert helpers.is_ip_address(address)


Expand Down