From: Tom Christie Date: Wed, 3 Jul 2019 09:33:38 +0000 (+0100) Subject: Minor tweaks in line with requests behavior (#110) X-Git-Tag: 0.6.6^0 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fe1f9ed1193e8824c9f1041117758741dd34600e;p=thirdparty%2Fhttpx.git Minor tweaks in line with requests behavior (#110) --- diff --git a/http3/__init__.py b/http3/__init__.py index 95b5e145..abc03caf 100644 --- a/http3/__init__.py +++ b/http3/__init__.py @@ -1,7 +1,9 @@ +from .__version__ import __description__, __title__, __version__ from .api import delete, get, head, options, patch, post, put, request from .client import AsyncClient, Client from .concurrency import AsyncioBackend from .config import ( + USER_AGENT, CertTypes, PoolLimits, SSLConfig, @@ -39,14 +41,22 @@ from .interfaces import ( from .models import ( URL, AsyncRequest, + AsyncRequestData, AsyncResponse, + AsyncResponseContent, + AuthTypes, Cookies, + CookieTypes, Headers, + HeaderTypes, Origin, QueryParams, + QueryParamTypes, Request, + RequestData, + RequestFiles, Response, + ResponseContent, + URLTypes, ) from .status_codes import StatusCode, codes - -__version__ = "0.6.5" diff --git a/http3/__version__.py b/http3/__version__.py new file mode 100644 index 00000000..2669a52f --- /dev/null +++ b/http3/__version__.py @@ -0,0 +1,3 @@ +__title__ = "http3" +__description__ = "A next generation HTTP client, for Python 3." +__version__ = "0.6.6" diff --git a/http3/client.py b/http3/client.py index 69b96b25..36569da2 100644 --- a/http3/client.py +++ b/http3/client.py @@ -17,7 +17,12 @@ from .dispatch.asgi import ASGIDispatch from .dispatch.connection_pool import ConnectionPool from .dispatch.threaded import ThreadedDispatcher from .dispatch.wsgi import WSGIDispatch -from .exceptions import RedirectBodyUnavailable, RedirectLoop, TooManyRedirects +from .exceptions import ( + InvalidURL, + RedirectBodyUnavailable, + RedirectLoop, + TooManyRedirects, +) from .interfaces import AsyncDispatcher, ConcurrencyBackend, Dispatcher from .models import ( URL, @@ -120,6 +125,10 @@ class BaseClient: auth = self.auth url = request.url + + if url.scheme not in ("http", "https"): + raise InvalidURL('URL scheme must be "http" or "https".') + if auth is None and (url.username or url.password): auth = HTTPBasicAuth(username=url.username, password=url.password) diff --git a/http3/config.py b/http3/config.py index 778051ba..4b0fe9e2 100644 --- a/http3/config.py +++ b/http3/config.py @@ -5,11 +5,15 @@ import typing import certifi +from .__version__ import __version__ + CertTypes = typing.Union[str, typing.Tuple[str, str]] VerifyTypes = typing.Union[str, bool] TimeoutTypes = typing.Union[float, typing.Tuple[float, float, float], "TimeoutConfig"] +USER_AGENT = f"python-http3/{__version__}" + DEFAULT_CIPHERS = ":".join( [ "ECDHE+AESGCM", diff --git a/http3/models.py b/http3/models.py index 1b5bb152..7981270e 100644 --- a/http3/models.py +++ b/http3/models.py @@ -10,6 +10,7 @@ from urllib.parse import parse_qsl, urlencode import chardet import rfc3986 +from .config import USER_AGENT from .decoders import ( ACCEPT_ENCODING, SUPPORTED_DECODERS, @@ -103,8 +104,6 @@ class URL: if not allow_relative: if not self.scheme: raise InvalidURL("No scheme included in URL.") - if self.scheme not in ("http", "https"): - raise InvalidURL('URL scheme must be "http" or "https".') if not self.host: raise InvalidURL("No host included in URL.") @@ -534,11 +533,12 @@ class BaseRequest: "content-length" in self.headers or "transfer-encoding" in self.headers ) has_accept_encoding = "accept-encoding" in self.headers + has_connection = "connection" in self.headers if not has_host: auto_headers.append((b"host", self.url.authority.encode("ascii"))) if not has_user_agent: - auto_headers.append((b"user-agent", b"http3")) + auto_headers.append((b"user-agent", USER_AGENT.encode("ascii"))) if not has_accept: auto_headers.append((b"accept", b"*/*")) if not has_content_length: @@ -549,6 +549,8 @@ class BaseRequest: auto_headers.append((b"content-length", content_length)) if not has_accept_encoding: auto_headers.append((b"accept-encoding", ACCEPT_ENCODING.encode())) + if not has_connection: + auto_headers.append((b"connection", b"keep-alive")) for item in reversed(auto_headers): self.headers.raw.insert(0, item) diff --git a/scripts/publish b/scripts/publish index 9ec45d54..cb02ec8f 100755 --- a/scripts/publish +++ b/scripts/publish @@ -1,7 +1,7 @@ #!/bin/sh -e export PACKAGE="http3" -export VERSION=`cat ${PACKAGE}/__init__.py | grep __version__ | sed "s/__version__ = //" | sed "s/'//g"` +export VERSION=`cat ${PACKAGE}/__version__.py | grep __version__ | sed "s/__version__ = //" | sed "s/'//g"` export PREFIX="" if [ -d 'venv' ] ; then export PREFIX="venv/bin/" diff --git a/tests/models/test_requests.py b/tests/models/test_requests.py index b5126bc7..66698010 100644 --- a/tests/models/test_requests.py +++ b/tests/models/test_requests.py @@ -86,8 +86,5 @@ def test_invalid_urls(): with pytest.raises(http3.InvalidURL): http3.Request("GET", "example.org") - with pytest.raises(http3.InvalidURL): - http3.Request("GET", "invalid://example.org") - with pytest.raises(http3.InvalidURL): http3.Request("GET", "http:///foo") diff --git a/tests/test_api.py b/tests/test_api.py index b417a817..0f89e562 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -83,3 +83,9 @@ def test_delete(server): response = http3.delete("http://127.0.0.1:8000/") assert response.status_code == 200 assert response.reason_phrase == "OK" + + +@threadpool +def test_get_invalid_url(server): + with pytest.raises(http3.InvalidURL): + http3.get("invalid://example.org")