Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: encode/httpx
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 0.25.2
Choose a base ref
...
head repository: encode/httpx
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 0.26.0
Choose a head ref
  • 19 commits
  • 36 files changed
  • 7 contributors

Commits on Nov 29, 2023

  1. Bump cryptography from 41.0.4 to 41.0.6 (#2965)

    Bumps [cryptography](https://github.com/pyca/cryptography) from 41.0.4 to 41.0.6.
    - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
    - [Commits](pyca/cryptography@41.0.4...41.0.6)
    
    ---
    updated-dependencies:
    - dependency-name: cryptography
      dependency-type: direct:production
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Nov 29, 2023

    Verified

    This commit was signed with the committer’s verified signature.
    kwasniew Mateusz Kwasniewski
    Copy the full SHA
    90d71e6 View commit details
  2. Ruff linter: Use the default line-length (#2922)

    Co-authored-by: Tester <Tester@test.com>
    Co-authored-by: Kar Petrosyan <92274156+karpetrosyan@users.noreply.github.com>
    3 people authored Nov 29, 2023

    Verified

    This commit was signed with the committer’s verified signature.
    kwasniew Mateusz Kwasniewski
    Copy the full SHA
    fd60b18 View commit details

Commits on Dec 1, 2023

  1. Bump ruff from 0.1.3 to 0.1.6 (#2974)

    Bumps [ruff](https://github.com/astral-sh/ruff) from 0.1.3 to 0.1.6.
    - [Release notes](https://github.com/astral-sh/ruff/releases)
    - [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
    - [Commits](astral-sh/ruff@v0.1.3...v0.1.6)
    
    ---
    updated-dependencies:
    - dependency-name: ruff
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Dec 1, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    d4b70fe View commit details
  2. Bump cryptography from 41.0.6 to 41.0.7 (#2971)

    Bumps [cryptography](https://github.com/pyca/cryptography) from 41.0.6 to 41.0.7.
    - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
    - [Commits](pyca/cryptography@41.0.6...41.0.7)
    
    ---
    updated-dependencies:
    - dependency-name: cryptography
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Dec 1, 2023
    Copy the full SHA
    0265d95 View commit details

Commits on Dec 2, 2023

  1. Bump trio-typing from 0.9.0 to 0.10.0 (#2970)

    Bumps [trio-typing](https://github.com/python-trio/trio-typing) from 0.9.0 to 0.10.0.
    - [Commits](python-trio/trio-typing@v0.9.0...v0.10.0)
    
    ---
    updated-dependencies:
    - dependency-name: trio-typing
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Dec 2, 2023
    Copy the full SHA
    fe5954c View commit details

Commits on Dec 3, 2023

  1. Bump mkdocs-material from 9.4.7 to 9.4.14 (#2973)

    Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.4.7 to 9.4.14.
    - [Release notes](https://github.com/squidfunk/mkdocs-material/releases)
    - [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG)
    - [Commits](squidfunk/mkdocs-material@9.4.7...9.4.14)
    
    ---
    updated-dependencies:
    - dependency-name: mkdocs-material
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    Co-authored-by: Kar Petrosyan <92274156+karpetrosyan@users.noreply.github.com>
    dependabot[bot] and karpetrosyan authored Dec 3, 2023
    Copy the full SHA
    266761d View commit details
  2. Bump uvicorn from 0.22.0 to 0.24.0.post1 (#2972)

    Bumps [uvicorn](https://github.com/encode/uvicorn) from 0.22.0 to 0.24.0.post1.
    - [Release notes](https://github.com/encode/uvicorn/releases)
    - [Changelog](https://github.com/encode/uvicorn/blob/master/CHANGELOG.md)
    - [Commits](encode/uvicorn@0.22.0...0.24.0.post1)
    
    ---
    updated-dependencies:
    - dependency-name: uvicorn
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    Co-authored-by: Kar Petrosyan <92274156+karpetrosyan@users.noreply.github.com>
    dependabot[bot] and karpetrosyan authored Dec 3, 2023
    Copy the full SHA
    9ef08c7 View commit details

Commits on Dec 5, 2023

  1. Reorganise tests in 'test_url.py' (#2981)

    * Reorganise tests in 'test_url.py'
    
    * Linting
    tomchristie authored Dec 5, 2023
    Copy the full SHA
    724eced View commit details
  2. Moving test cases into 'test_url.py' (#2982)

    * Moving test cases into 'test_url.py'
    
    * Move test_url to test_basic_url
    
    * Linting
    
    * Move TypeError test case. Move basic httpx.URL cases.
    
    * Linting
    
    * Merge invalid URL cases
    
    * Move percent encoding test cases
    
    * Move remaining test cases
    
    * Linting
    
    * Add missing test cases
    tomchristie authored Dec 5, 2023
    Copy the full SHA
    5b5f6d8 View commit details

Commits on Dec 7, 2023

  1. Allow URLs where username or password contains unescaped '@'. (#2986)

    * Add test cases for userinfo in URL
    
    * Resolve failing test cases
    
    * Update CHANGELOG.md
    
    * Update CHANGELOG.md
    tomchristie authored Dec 7, 2023
    Copy the full SHA
    b471f01 View commit details

Commits on Dec 11, 2023

  1. Add the 'proxy' parameter and deprecate 'proxies'. (#2879)

    * Add the proxy parameter and deprecate proxies
    
    * Make the Client.proxy and HTTPTransport.proxy types the same
    
    * Update httpx/_transports/default.py
    
    Co-authored-by: T-256 <132141463+T-256@users.noreply.github.com>
    
    * Update httpx/_transports/default.py
    
    Co-authored-by: T-256 <132141463+T-256@users.noreply.github.com>
    
    * Drop unneeded noqa
    
    * Changelog
    
    * update documentation
    
    * Allow None in mounts
    
    * typos
    
    * Update httpx/_types.py
    
    * Changes proxies to proxy in CLI app
    
    * Add proxy to request function
    
    * Update CHANGELOG.md
    
    Co-authored-by: Tom Christie <tom@tomchristie.com>
    
    * Update docs/troubleshooting.md
    
    Co-authored-by: Tom Christie <tom@tomchristie.com>
    
    * Update docs/troubleshooting.md
    
    Co-authored-by: Tom Christie <tom@tomchristie.com>
    
    * Lint
    
    ---------
    
    Co-authored-by: Tom Christie <tom@tomchristie.com>
    Co-authored-by: T-256 <132141463+T-256@users.noreply.github.com>
    3 people authored Dec 11, 2023
    Copy the full SHA
    f8981f3 View commit details
  2. Copy the full SHA
    90538a3 View commit details
  3. Copy the full SHA
    1e11096 View commit details

Commits on Dec 12, 2023

  1. Copy the full SHA
    2c51edd View commit details

Commits on Dec 13, 2023

  1. Enabling ruff C416 (#3001)

    * Enabled C416 in ruff
    
    * Ran ruff on all files
    
    * Ran ruff format
    
    * Update pyproject.toml
    
    ---------
    
    Co-authored-by: Tom Christie <tom@tomchristie.com>
    jamesbraza and tomchristie authored Dec 13, 2023
    Copy the full SHA
    2318fd8 View commit details

Commits on Dec 14, 2023

  1. Fix environment proxies (#2741)

    * Add red test
    
    * Make the test pass
    
    * Lint
    
    * chanelog
    
    ---------
    
    Co-authored-by: Karen Petrosyan <92274156+karosis88@users.noreply.github.com>
    Co-authored-by: Tom Christie <tom@tomchristie.com>
    3 people authored Dec 14, 2023
    Copy the full SHA
    3b9060e View commit details

Commits on Dec 15, 2023

  1. Cleanup URL percent-encoding behavior. (#2990)

    * Replace path_query_fragment encoding tests
    
    * Remove replaced test cases
    
    * Fix test case to use correct hex sequence for 'abc'
    
    * Fix 'quote' behaviour so we don't double-escape.
    
    * Add '/' to safe chars in query strings
    
    * Update docstring
    
    * Linting
    
    * Update outdated comment.
    
    * Revert unrelated change
    
    ---------
    
    Co-authored-by: Kar Petrosyan <92274156+karpetrosyan@users.noreply.github.com>
    tomchristie and karpetrosyan authored Dec 15, 2023
    Copy the full SHA
    a11fc38 View commit details

Commits on Dec 19, 2023

  1. Copy the full SHA
    b4b27ff View commit details

Commits on Dec 20, 2023

  1. Version 0.26.0 (#3009)

    * Version 0.26.0
    
    * Update changelog
    
    * Update CHANGELOG.md
    
    * Add `Deprecated` section
    karpetrosyan authored Dec 20, 2023
    Copy the full SHA
    08eff92 View commit details
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -4,6 +4,24 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## 0.26.0 (20th December, 2023)

### Added

* The `proxy` argument was added. You should use the `proxy` argument instead of the deprecated `proxies`, or use `mounts=` for more complex configurations. (#2879)

### Deprecated

* The `proxies` argument is now deprecated. It will still continue to work, but it will be removed in the future. (#2879)

### Fixed

* Fix cases of double escaping of URL path components. Allow / as a safe character in the query portion. (#2990)
* Handle `NO_PROXY` envvar cases when a fully qualified URL is supplied as the value. (#2741)
* Allow URLs where username or password contains unescaped '@'. (#2986)
* Ensure ASGI `raw_path` does not include URL query component. (#2999)
* Ensure `Response.iter_text()` cannot yield empty strings. (#2998)

## 0.25.2 (24th November, 2023)

### Added
264 changes: 132 additions & 132 deletions docs/advanced.md
Original file line number Diff line number Diff line change
@@ -504,7 +504,7 @@ The `NetRCAuth()` class uses [the `netrc.netrc()` function from the Python stand

## HTTP Proxying

HTTPX supports setting up [HTTP proxies](https://en.wikipedia.org/wiki/Proxy_server#Web_proxy_servers) via the `proxies` parameter to be passed on client initialization or top-level API functions like `httpx.get(..., proxies=...)`.
HTTPX supports setting up [HTTP proxies](https://en.wikipedia.org/wiki/Proxy_server#Web_proxy_servers) via the `proxy` parameter to be passed on client initialization or top-level API functions like `httpx.get(..., proxy=...)`.

<div align="center">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/2/27/Open_proxy_h2g2bob.svg/480px-Open_proxy_h2g2bob.svg.png"/>
@@ -516,19 +516,19 @@ HTTPX supports setting up [HTTP proxies](https://en.wikipedia.org/wiki/Proxy_ser
To route all traffic (HTTP and HTTPS) to a proxy located at `http://localhost:8030`, pass the proxy URL to the client...

```python
with httpx.Client(proxies="http://localhost:8030") as client:
with httpx.Client(proxy="http://localhost:8030") as client:
...
```

For more advanced use cases, pass a proxies `dict`. For example, to route HTTP and HTTPS requests to 2 different proxies, respectively located at `http://localhost:8030`, and `http://localhost:8031`, pass a `dict` of proxy URLs:
For more advanced use cases, pass a mounts `dict`. For example, to route HTTP and HTTPS requests to 2 different proxies, respectively located at `http://localhost:8030`, and `http://localhost:8031`, pass a `dict` of proxy URLs:

```python
proxies = {
"http://": "http://localhost:8030",
"https://": "http://localhost:8031",
proxy_mounts = {
"http://": httpx.HTTPTransport(proxy="http://localhost:8030"),
"https://": httpx.HTTPTransport(proxy="http://localhost:8031"),
}

with httpx.Client(proxies=proxies) as client:
with httpx.Client(mounts=proxy_mounts) as client:
...
```

@@ -546,132 +546,10 @@ For detailed information about proxy routing, see the [Routing](#routing) sectio
Proxy credentials can be passed as the `userinfo` section of the proxy URL. For example:

```python
proxies = {
"http://": "http://username:password@localhost:8030",
# ...
}
```

### Routing

HTTPX provides fine-grained controls for deciding which requests should go through a proxy, and which shouldn't. This process is known as proxy routing.

The `proxies` dictionary maps URL patterns ("proxy keys") to proxy URLs. HTTPX matches requested URLs against proxy keys to decide which proxy should be used, if any. Matching is done from most specific proxy keys (e.g. `https://<domain>:<port>`) to least specific ones (e.g. `https://`).

HTTPX supports routing proxies based on **scheme**, **domain**, **port**, or a combination of these.

#### Wildcard routing

Route everything through a proxy...

```python
proxies = {
"all://": "http://localhost:8030",
}
```

#### Scheme routing

Route HTTP requests through one proxy, and HTTPS requests through another...

```python
proxies = {
"http://": "http://localhost:8030",
"https://": "http://localhost:8031",
}
```

#### Domain routing

Proxy all requests on domain "example.com", let other requests pass through...

```python
proxies = {
"all://example.com": "http://localhost:8030",
}
```

Proxy HTTP requests on domain "example.com", let HTTPS and other requests pass through...

```python
proxies = {
"http://example.com": "http://localhost:8030",
}
```

Proxy all requests to "example.com" and its subdomains, let other requests pass through...

```python
proxies = {
"all://*example.com": "http://localhost:8030",
}
```

Proxy all requests to strict subdomains of "example.com", let "example.com" and other requests pass through...

```python
proxies = {
"all://*.example.com": "http://localhost:8030",
}
```

#### Port routing

Proxy HTTPS requests on port 1234 to "example.com"...

```python
proxies = {
"https://example.com:1234": "http://localhost:8030",
}
```

Proxy all requests on port 1234...

```python
proxies = {
"all://*:1234": "http://localhost:8030",
}
```

#### No-proxy support

It is also possible to define requests that _shouldn't_ be routed through proxies.

To do so, pass `None` as the proxy URL. For example...

```python
proxies = {
# Route requests through a proxy by default...
"all://": "http://localhost:8031",
# Except those for "example.com".
"all://example.com": None,
}
```

#### Complex configuration example

You can combine the routing features outlined above to build complex proxy routing configurations. For example...

```python
proxies = {
# Route all traffic through a proxy by default...
"all://": "http://localhost:8030",
# But don't use proxies for HTTPS requests to "domain.io"...
"https://domain.io": None,
# And use another proxy for requests to "example.com" and its subdomains...
"all://*example.com": "http://localhost:8031",
# And yet another proxy if HTTP is used,
# and the "internal" subdomain on port 5550 is requested...
"http://internal.example.com:5550": "http://localhost:8032",
}
with httpx.Client(proxy="http://username:password@localhost:8030") as client:
...
```

#### Environment variables

HTTP proxying can also be configured through environment variables, although with less fine-grained control.

See documentation on [`HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`](environment_variables.md#http_proxy-https_proxy-all_proxy) for more information.

### Proxy mechanisms

!!! note
@@ -707,7 +585,7 @@ $ pip install httpx[socks]
You can now configure a client to make requests via a proxy using the SOCKS protocol:

```python
httpx.Client(proxies='socks5://user:pass@host:port')
httpx.Client(proxy='socks5://user:pass@host:port')
```

## Timeout Configuration
@@ -1294,3 +1172,125 @@ Adding support for custom schemes:
mounts = {"file://": FileSystemTransport()}
client = httpx.Client(mounts=mounts)
```

### Routing

HTTPX provides a powerful mechanism for routing requests, allowing you to write complex rules that specify which transport should be used for each request.

The `mounts` dictionary maps URL patterns to HTTP transports. HTTPX matches requested URLs against URL patterns to decide which transport should be used, if any. Matching is done from most specific URL patterns (e.g. `https://<domain>:<port>`) to least specific ones (e.g. `https://`).

HTTPX supports routing requests based on **scheme**, **domain**, **port**, or a combination of these.

#### Wildcard routing

Route everything through a transport...

```python
mounts = {
"all://": httpx.HTTPTransport(proxy="http://localhost:8030"),
}
```

#### Scheme routing

Route HTTP requests through one transport, and HTTPS requests through another...

```python
mounts = {
"http://": httpx.HTTPTransport(proxy="http://localhost:8030"),
"https://": httpx.HTTPTransport(proxy="http://localhost:8031"),
}
```

#### Domain routing

Proxy all requests on domain "example.com", let other requests pass through...

```python
mounts = {
"all://example.com": httpx.HTTPTransport(proxy="http://localhost:8030"),
}
```

Proxy HTTP requests on domain "example.com", let HTTPS and other requests pass through...

```python
mounts = {
"http://example.com": httpx.HTTPTransport(proxy="http://localhost:8030"),
}
```

Proxy all requests to "example.com" and its subdomains, let other requests pass through...

```python
mounts = {
"all://*example.com": httpx.HTTPTransport(proxy="http://localhost:8030"),
}
```

Proxy all requests to strict subdomains of "example.com", let "example.com" and other requests pass through...

```python
mounts = {
"all://*.example.com": httpx.HTTPTransport(proxy="http://localhost:8030"),
}
```

#### Port routing

Proxy HTTPS requests on port 1234 to "example.com"...

```python
mounts = {
"https://example.com:1234": httpx.HTTPTransport(proxy="http://localhost:8030"),
}
```

Proxy all requests on port 1234...

```python
mounts = {
"all://*:1234": httpx.HTTPTransport(proxy="http://localhost:8030"),
}
```

#### No-proxy support

It is also possible to define requests that _shouldn't_ be routed through the transport.

To do so, pass `None` as the proxy URL. For example...

```python
mounts = {
# Route requests through a proxy by default...
"all://": httpx.HTTPTransport(proxy="http://localhost:8031"),
# Except those for "example.com".
"all://example.com": None,
}
```

#### Complex configuration example

You can combine the routing features outlined above to build complex proxy routing configurations. For example...

```python
mounts = {
# Route all traffic through a proxy by default...
"all://": httpx.HTTPTransport(proxy="http://localhost:8030"),
# But don't use proxies for HTTPS requests to "domain.io"...
"https://domain.io": None,
# And use another proxy for requests to "example.com" and its subdomains...
"all://*example.com": httpx.HTTPTransport(proxy="http://localhost:8031"),
# And yet another proxy if HTTP is used,
# and the "internal" subdomain on port 5550 is requested...
"http://internal.example.com:5550": httpx.HTTPTransport(proxy="http://localhost:8032"),
}
```

#### Environment variables

There are also environment variables that can be used to control the dictionary of the client mounts.
They can be used to configure HTTP proxying for clients.

See documentation on [`HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`](environment_variables.md#http_proxy-https_proxy-all_proxy) for more information.

12 changes: 8 additions & 4 deletions docs/compatibility.md
Original file line number Diff line number Diff line change
@@ -157,13 +157,17 @@ httpx.get('https://www.example.com', timeout=None)

## Proxy keys

When using `httpx.Client(proxies={...})` to map to a selection of different proxies, we use full URL schemes, such as `proxies={"http://": ..., "https://": ...}`.
HTTPX uses the mounts argument for HTTP proxying and transport routing.
It can do much more than proxies and allows you to configure more than just the proxy route.
For more detailed documentation, see [Mounting Transports](advanced.md#mounting-transports).

When using `httpx.Client(mounts={...})` to map to a selection of different transports, we use full URL schemes, such as `mounts={"http://": ..., "https://": ...}`.

This is different to the `requests` usage of `proxies={"http": ..., "https": ...}`.

This change is for better consistency with more complex mappings, that might also include domain names, such as `proxies={"all://": ..., "all://www.example.com": None}` which maps all requests onto a proxy, except for requests to "www.example.com" which have an explicit exclusion.
This change is for better consistency with more complex mappings, that might also include domain names, such as `mounts={"all://": ..., httpx.HTTPTransport(proxy="all://www.example.com": None})` which maps all requests onto a proxy, except for requests to "www.example.com" which have an explicit exclusion.

Also note that `requests.Session.request(...)` allows a `proxies=...` parameter, whereas `httpx.Client.request(...)` does not.
Also note that `requests.Session.request(...)` allows a `proxies=...` parameter, whereas `httpx.Client.request(...)` does not allow `mounts=...`.

## SSL configuration

@@ -195,7 +199,7 @@ We don't support `response.is_ok` since the naming is ambiguous there, and might

There is no notion of [prepared requests](https://requests.readthedocs.io/en/stable/user/advanced/#prepared-requests) in HTTPX. If you need to customize request instantiation, see [Request instances](advanced.md#request-instances).

Besides, `httpx.Request()` does not support the `auth`, `timeout`, `follow_redirects`, `proxies`, `verify` and `cert` parameters. However these are available in `httpx.request`, `httpx.get`, `httpx.post` etc., as well as on [`Client` instances](advanced.md#client-instances).
Besides, `httpx.Request()` does not support the `auth`, `timeout`, `follow_redirects`, `mounts`, `verify` and `cert` parameters. However these are available in `httpx.request`, `httpx.get`, `httpx.post` etc., as well as on [`Client` instances](advanced.md#client-instances).

## Mocking

4 changes: 1 addition & 3 deletions docs/contributing.md
Original file line number Diff line number Diff line change
@@ -213,9 +213,7 @@ this is where our previously generated `client.pem` comes in:
```
import httpx
proxies = {"all://": "http://127.0.0.1:8080/"}
with httpx.Client(proxies=proxies, verify="/path/to/client.pem") as client:
with httpx.Client(proxy="http://127.0.0.1:8080/", verify="/path/to/client.pem") as client:
response = client.get("https://example.org")
print(response.status_code) # should print 200
```
Loading