From: Tom Christie Date: Fri, 6 Dec 2019 11:29:22 +0000 (+0000) Subject: Warn if cert / verify / trust_env are passed to client.request() (#597) X-Git-Tag: 0.9.0~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1e23855709988b012f195fcfddfcf80d5e703841;p=thirdparty%2Fhttpx.git Warn if cert / verify / trust_env are passed to client.request() (#597) * Add cert and verify warnings on Client.request * Resolve typo Co-Authored-By: Florimond Manca * Resolve typo Co-Authored-By: Florimond Manca * trust_env should be set on client init * Update docs for per-Client SSL settings * Update requests compat docs --- diff --git a/docs/advanced.md b/docs/advanced.md index 69d20d9a..6f8a4d98 100644 --- a/docs/advanced.md +++ b/docs/advanced.md @@ -174,6 +174,12 @@ password example-password ... ``` +When using `Client` instances, `trust_env` should be set on the client itself, rather that on the request methods: + +```python +client = httpx.Client(trust_env=False) +``` + ## Unix Domain Sockets You can configure an `httpx` client to connect through a unix domain socket via the `uds` parameter. This is useful when making requests to a server that is bound to a socket file rather than an IP address. @@ -373,13 +379,11 @@ MIME header field. When making a request over HTTPS, HTTPX needs to verify the identity of the requested host. To do this, it uses a bundle of SSL certificates (a.k.a. CA bundle) delivered by a trusted certificate authority (CA). -### Default CA bundle +### Changing the verification defaults By default, HTTPX uses the CA bundle provided by [Certifi](https://pypi.org/project/certifi/). This is what you want in most cases, even though some advanced situations may require you to use a different set of certificates. -### Using a custom CA bundle - -If you'd like to use a custom CA bundle, you can use the `verify` parameter that is available on the high-level API as well as clients. For example: +If you'd like to use a custom CA bundle, you can use the `verify` parameter. ```python import httpx @@ -387,6 +391,24 @@ import httpx r = await httpx.get("https://example.org", verify="path/to/client.pem") ``` +You can also disable the SSL verification... + +```python +import httpx + +r = await httpx.get("https://example.org", verify=False) +``` + +### SSL configuration on client instances + +If you're using a `Client()` instance, then you should pass any SSL settings when instantiating the client. + +```python +client = httpx.Client(verify=False) +``` + +The `client.get(...)` method and other request methods *do not* changing the SSL settings on a per-request basis. If you need different SSL settings in different cases you should use more that one client instance, with different settings on each. Each client will then be using an isolated connection pool with a specific fixed SSL configuration on all connections within that pool. + ### Making HTTPS requests to a local server When making requests to local servers, such as a development server running on `localhost`, you will typically be using unencrypted HTTP connections. diff --git a/docs/compatibility.md b/docs/compatibility.md index f77512fa..d63df7e4 100644 --- a/docs/compatibility.md +++ b/docs/compatibility.md @@ -4,20 +4,53 @@ HTTPX aims to be compatible with the `requests` API wherever possible. This documentation outlines places where the API differs... -## QuickStart +## Request URLS -Pretty much any API mentioned in the `requests` QuickStart should be identical -to the API in our own documentation. The following exceptions apply: +Accessing `response.url` will return a `URL` instance, rather than a string. +Use `str(response.url)` if you need a string instance. -* `Response.url` - Returns a `URL` instance, rather than a string. Use `str(response.url)` if you need a string instance. -* `httpx.codes` - In our documentation we prefer the uppercased versions, such as `codes.NOT_FOUND`, but also provide lower-cased versions for API compatibility with `requests`. -* `stream()`. - HTTPX provides a `.stream()` interface rather than using `stream=True`. This ensures that streaming responses are always properly closed outside of the stream block, and makes it visually clearer at which points streaming I/O APIs may be used with a response. Streaming request data is made avialable with `.stream_bytes()`, `.stream_text()`, `.stream_lines()`, and `.stream_raw()`. -* `.get`, `.delete`, `.head`, `.options` - These methods do not support `files`, `data`, or `json` arguments. Use `.request` if you need to need to send data using these http methods. -* We don't support `response.is_ok` since the naming is ambiguous there, and might incorrectly imply an equivalence to `response.status_code == codes.OK`. Instead we provide the `response.is_error` property. Use `if not response.is_error:` instead of `if response.is_ok:`. +## Status Codes -## Advanced Usage +In our documentation we prefer the uppercased versions, such as `codes.NOT_FOUND`, but also provide lower-cased versions for API compatibility with `requests`. -### requests.Session +Requests includes various synoynms for status codes that HTTPX does not support. + +## Streaming responses + +HTTPX provides a `.stream()` interface rather than using `stream=True`. This ensures that streaming responses are always properly closed outside of the stream block, and makes it visually clearer at which points streaming I/O APIs may be used with a response. + +For example: + +```python +async with request.stream("GET", "https://www.example.com") as response: + ... +``` + +Within a `stream()` block request data is made available with: + +* `.stream_bytes()` - Instead of `response.iter_content()` +* `.stream_text()` - Instead of `response.iter_content(decode_unicode=True)` +* `.stream_lines()` - Instead of `response.iter_lines()` +* `.stream_raw()` - Use this instead of `response.raw` +* `.read()` - Read the entire response body, making `request.text` and `response.content` available. + +## SSL configuration + +When using a `Client` instance, the `trust_env`, `verify`, and `cert` arguments should always be passed on client instantiation, rather than passed to the request method. + +If you need more than one different SSL configuration, you should use different client instances for each SSL configuration. + +## Request body on HTTP methods + +The HTTP `GET`, `DELETE`, `HEAD`, and `OPTIONS` methods are specified as not supporting a request body. To stay in line with this, the `.get`, `.delete`, `.head` and `.options` functions do not support `files`, `data`, or `json` arguments. + +If you really do need to send request data using these http methods you should use the generic `.request` function instead. + +## Checking for 4xx/5xx responses + +We don't support `response.is_ok` since the naming is ambiguous there, and might incorrectly imply an equivalence to `response.status_code == codes.OK`. Instead we provide the `response.is_error` property. Use `if not response.is_error:` instead of `if response.is_ok:`. + +## Client instances The HTTPX equivalent of `requests.Session` is `httpx.Client`. @@ -31,8 +64,6 @@ is generally equivalent to client = httpx.Client(**kwargs) ``` -More detailed documentation and usage of `Client` can be found in [Advanced Usage](advanced.md). - ## Mocking If you need to mock HTTPX the same way that test utilities like `responses` and `requests-mock` does for `requests`, see [RESPX](https://github.com/lundberg/respx). diff --git a/docs/environment_variables.md b/docs/environment_variables.md index 4fbd4b3c..bd41c83d 100644 --- a/docs/environment_variables.md +++ b/docs/environment_variables.md @@ -2,14 +2,12 @@ Environment Variables ===================== The HTTPX library can be configured via environment variables. -Environment variables are used by default. To ignore environment variables, `trust_env` has to be set `False`. -There are two ways to set `trust_env` to disable environment variables: +Environment variables are used by default. To ignore environment variables, `trust_env` has to be set `False`. There are two ways to set `trust_env` to disable environment variables: -* On the client via `httpx.Client(trust_env=False)` -* Per request via `client.get("", trust_env=False)` +* On the client via `httpx.Client(trust_env=False)`. +* Using the top-level API, such as `httpx.get("", trust_env=False)`. -Here is a list of environment variables that HTTPX recognizes -and what function they serve: +Here is a list of environment variables that HTTPX recognizes and what function they serve: `HTTPX_LOG_LEVEL` ----------------- diff --git a/httpx/client.py b/httpx/client.py index a4fd8a34..4da7ba15 100644 --- a/httpx/client.py +++ b/httpx/client.py @@ -223,6 +223,24 @@ class Client: timeout: typing.Union[TimeoutTypes, UnsetType] = UNSET, trust_env: bool = None, ) -> Response: + if cert is not None: + warnings.warn( + "Passing a 'cert' argument when making a request on a client " + "is due to be deprecated. Instantiate a new client instead, " + "passing any 'cert' arguments to the client itself." + ) + if verify is not None: + warnings.warn( + "Passing a 'verify' argument when making a request on a client " + "is due to be deprecated. Instantiate a new client instead, " + "passing any 'verify' arguments to the client itself." + ) + if trust_env is not None: + warnings.warn( + "Passing a 'trust_env' argument when making a request on a client " + "is due to be deprecated. Instantiate a new client instead, " + "passing any 'trust_env' argument to the client itself." + ) if stream: warnings.warn( "The 'stream=True' argument is due to be deprecated. "