You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
208 lines
7.1 KiB
208 lines
7.1 KiB
"""Proxy tests.
|
|
|
|
Tests do modify `os.environ` global states. Each test must be run in separate
|
|
process. Must use `pytest --forked` or similar technique.
|
|
"""
|
|
|
|
from __future__ import absolute_import
|
|
from __future__ import division
|
|
from __future__ import print_function
|
|
|
|
import httplib2
|
|
import mock
|
|
import os
|
|
import pytest
|
|
import socket
|
|
import tests
|
|
from six.moves import urllib
|
|
|
|
|
|
def _raise_name_not_known_error(*args, **kwargs):
|
|
raise socket.gaierror(socket.EAI_NONAME, "Name or service not known")
|
|
|
|
|
|
def test_from_url():
|
|
pi = httplib2.proxy_info_from_url("http://myproxy.example.com")
|
|
assert pi.proxy_host == "myproxy.example.com"
|
|
assert pi.proxy_port == 80
|
|
assert pi.proxy_user is None
|
|
|
|
|
|
def test_from_url_ident():
|
|
pi = httplib2.proxy_info_from_url("http://zoidberg:fish@someproxy:99")
|
|
assert pi.proxy_host == "someproxy"
|
|
assert pi.proxy_port == 99
|
|
assert pi.proxy_user == "zoidberg"
|
|
assert pi.proxy_pass == "fish"
|
|
|
|
|
|
def test_from_env(monkeypatch):
|
|
assert os.environ.get("http_proxy") is None
|
|
monkeypatch.setenv("http_proxy", "http://myproxy.example.com:8080")
|
|
pi = httplib2.proxy_info_from_environment()
|
|
assert pi.proxy_host == "myproxy.example.com"
|
|
assert pi.proxy_port == 8080
|
|
|
|
|
|
def test_from_env_https(monkeypatch):
|
|
assert os.environ.get("http_proxy") is None
|
|
monkeypatch.setenv("http_proxy", "http://myproxy.example.com:80")
|
|
monkeypatch.setenv("https_proxy", "http://myproxy.example.com:81")
|
|
pi = httplib2.proxy_info_from_environment("https")
|
|
assert pi.proxy_host == "myproxy.example.com"
|
|
assert pi.proxy_port == 81
|
|
|
|
|
|
def test_from_env_none():
|
|
os.environ.clear()
|
|
pi = httplib2.proxy_info_from_environment()
|
|
assert pi is None
|
|
|
|
|
|
def test_applies_to(monkeypatch):
|
|
monkeypatch.setenv("http_proxy", "http://myproxy.example.com:80")
|
|
monkeypatch.setenv("https_proxy", "http://myproxy.example.com:81")
|
|
monkeypatch.setenv("no_proxy", "localhost,example.com,.wildcard")
|
|
pi = httplib2.proxy_info_from_environment()
|
|
assert not pi.applies_to("localhost")
|
|
assert pi.applies_to("www.google.com")
|
|
assert pi.applies_to("prefixlocalhost")
|
|
assert pi.applies_to("www.example.com")
|
|
assert pi.applies_to("sub.example.com")
|
|
assert not pi.applies_to("sub.wildcard")
|
|
assert not pi.applies_to("pub.sub.wildcard")
|
|
|
|
|
|
def test_noproxy_trailing_comma(monkeypatch):
|
|
monkeypatch.setenv("http_proxy", "http://myproxy.example.com:80")
|
|
monkeypatch.setenv("no_proxy", "localhost,other.host,")
|
|
pi = httplib2.proxy_info_from_environment()
|
|
assert not pi.applies_to("localhost")
|
|
assert not pi.applies_to("other.host")
|
|
assert pi.applies_to("example.domain")
|
|
|
|
|
|
def test_noproxy_star(monkeypatch):
|
|
monkeypatch.setenv("http_proxy", "http://myproxy.example.com:80")
|
|
monkeypatch.setenv("NO_PROXY", "*")
|
|
pi = httplib2.proxy_info_from_environment()
|
|
for host in ("localhost", "169.254.38.192", "www.google.com"):
|
|
assert not pi.applies_to(host)
|
|
|
|
|
|
def test_headers():
|
|
headers = {"key0": "val0", "key1": "val1"}
|
|
pi = httplib2.ProxyInfo(
|
|
httplib2.socks.PROXY_TYPE_HTTP, "localhost", 1234, proxy_headers=headers
|
|
)
|
|
assert pi.proxy_headers == headers
|
|
|
|
|
|
@pytest.mark.skipif(
|
|
os.environ.get("TRAVIS_PYTHON_VERSION") in ("2.7", "pypy"),
|
|
reason="Fails on Travis py27/pypy, works elsewhere. "
|
|
"See https://travis-ci.org/httplib2/httplib2/jobs/408769880.",
|
|
)
|
|
@mock.patch("socket.socket.connect", spec=True)
|
|
def test_server_not_found_error_is_raised_for_invalid_hostname(mock_socket_connect):
|
|
"""Invalidates https://github.com/httplib2/httplib2/pull/100."""
|
|
mock_socket_connect.side_effect = _raise_name_not_known_error
|
|
http = httplib2.Http(
|
|
proxy_info=httplib2.ProxyInfo(
|
|
httplib2.socks.PROXY_TYPE_HTTP, "255.255.255.255", 8001
|
|
)
|
|
)
|
|
with tests.assert_raises(httplib2.ServerNotFoundError):
|
|
http.request("http://invalid.hostname.foo.bar/", "GET")
|
|
|
|
|
|
def test_auth_str_bytes():
|
|
# https://github.com/httplib2/httplib2/pull/115
|
|
# Proxy-Authorization b64encode() TypeError: a bytes-like object is required, not 'str'
|
|
with tests.server_const_http(request_count=2) as uri:
|
|
uri_parsed = urllib.parse.urlparse(uri)
|
|
http = httplib2.Http(
|
|
proxy_info=httplib2.ProxyInfo(
|
|
httplib2.socks.PROXY_TYPE_HTTP,
|
|
proxy_host=uri_parsed.hostname,
|
|
proxy_port=uri_parsed.port,
|
|
proxy_rdns=True,
|
|
proxy_user=u"user_str",
|
|
proxy_pass=u"pass_str",
|
|
)
|
|
)
|
|
response, _ = http.request(uri, "GET")
|
|
assert response.status == 200
|
|
|
|
with tests.server_const_http(request_count=2) as uri:
|
|
uri_parsed = urllib.parse.urlparse(uri)
|
|
http = httplib2.Http(
|
|
proxy_info=httplib2.ProxyInfo(
|
|
httplib2.socks.PROXY_TYPE_HTTP,
|
|
proxy_host=uri_parsed.hostname,
|
|
proxy_port=uri_parsed.port,
|
|
proxy_rdns=True,
|
|
proxy_user=b"user_bytes",
|
|
proxy_pass=b"pass_bytes",
|
|
)
|
|
)
|
|
response, _ = http.request(uri, "GET")
|
|
assert response.status == 200
|
|
|
|
|
|
def test_socks5_auth():
|
|
def proxy_conn(client, tick):
|
|
data = client.recv(64)
|
|
assert data == b"\x05\x02\x00\x02"
|
|
client.send(b"\x05\x02") # select username/password auth
|
|
data = client.recv(64)
|
|
assert data == b"\x01\x08user_str\x08pass_str"
|
|
client.send(b"\x01\x01") # deny
|
|
tick(None)
|
|
|
|
with tests.server_socket(proxy_conn) as uri:
|
|
uri_parsed = urllib.parse.urlparse(uri)
|
|
proxy_info = httplib2.ProxyInfo(
|
|
httplib2.socks.PROXY_TYPE_SOCKS5,
|
|
proxy_host=uri_parsed.hostname,
|
|
proxy_port=uri_parsed.port,
|
|
proxy_rdns=True,
|
|
proxy_user=u"user_str",
|
|
proxy_pass=u"pass_str",
|
|
)
|
|
http = httplib2.Http(proxy_info=proxy_info)
|
|
with tests.assert_raises(httplib2.socks.Socks5AuthError):
|
|
http.request(uri, "GET")
|
|
|
|
|
|
def test_functional_noproxy_star_http(monkeypatch):
|
|
def handler(request):
|
|
if request.method == "CONNECT":
|
|
return tests.http_response_bytes(
|
|
status="400 Expected direct", headers={"connection": "close"},
|
|
)
|
|
return tests.http_response_bytes()
|
|
|
|
with tests.server_request(handler) as uri:
|
|
monkeypatch.setenv("http_proxy", uri)
|
|
monkeypatch.setenv("no_proxy", "*")
|
|
http = httplib2.Http()
|
|
response, _ = http.request(uri, "GET")
|
|
assert response.status == 200
|
|
|
|
|
|
def test_functional_noproxy_star_https(monkeypatch):
|
|
def handler(request):
|
|
if request.method == "CONNECT":
|
|
return tests.http_response_bytes(
|
|
status="400 Expected direct", headers={"connection": "close"},
|
|
)
|
|
return tests.http_response_bytes()
|
|
|
|
with tests.server_request(handler, tls=True) as uri:
|
|
monkeypatch.setenv("https_proxy", uri)
|
|
monkeypatch.setenv("no_proxy", "*")
|
|
http = httplib2.Http(ca_certs=tests.CA_CERTS)
|
|
response, _ = http.request(uri, "GET")
|
|
assert response.status == 200
|