From 7d3d04d57ae75fb72bece5f122a05ed46a5ea654 Mon Sep 17 00:00:00 2001 From: Marc <50042689+mrcsnv@users.noreply.github.com> Date: Tue, 14 Apr 2026 15:07:01 +0200 Subject: [PATCH 1/3] Enhance proxy usage documentation with the correct usage. Expanded the proxy usage documentation to include authentication, per-request proxies with custom headers, and clarified Unix socket proxy usage. --- docs/source/guide/proxy.md | 148 +++++++++++++++++++++++++++++-------- 1 file changed, 118 insertions(+), 30 deletions(-) diff --git a/docs/source/guide/proxy.md b/docs/source/guide/proxy.md index cec9ad19..6c64b16a 100644 --- a/docs/source/guide/proxy.md +++ b/docs/source/guide/proxy.md @@ -2,67 +2,155 @@ !!! info "On this page" - HTTP/HTTPS proxy - - Unix Socket proxy + - Proxy with Authentication + - Per-request proxy with custom headers + - Unix Socket proxy for local services (Docker, Podman) + - Constructor reference and choosing the right one -### HTTP/HTTPS Proxy +The `Proxy` class provides several constructors depending on what you want to intercept: -Using proxies with authentication: +| Constructor | What it proxies | +|---|---| +| `Proxy.all(url)` | All requests (HTTP + HTTPS) | +| `Proxy.http(url)` | HTTP requests only | +| `Proxy.https(url)` | HTTPS requests only | +| `Proxy.unix(path)` | Requests via a Unix socket | + +You can pass a proxy in two ways: +- **Per-client** via `Client(proxies=[...])` — applies to every request made by that client. +- **Per-request** via `wreq.get(..., proxy=...)` — overrides or sets a proxy for a single request. + +--- + +## HTTP / HTTPS Proxy + +### Basic usage with a client ```python import asyncio -import wreq from wreq import Client, Proxy - async def main(): - # Create a client with multiple proxies client = Client( - proxies=[Proxy.http("socks5h://abc:def@127.0.0.1:6152")], + proxies=[Proxy.all("http://proxy.example.com:8080")] ) - # Send request via the client proxy - resp = await client.get("https://httpbin.io/anything") + resp = await client.get("https://httpbin.io/ip") print(await resp.text()) - # Send request via custom proxy +asyncio.run(main()) +``` + +All requests made through this `client` will be routed via the proxy. + +--- + +### Proxy with authentication + +If your proxy requires credentials, include them directly in the URL using the `username:password@host:port` syntax. + +**HTTP / HTTPS proxy with credentials:** + +```python +proxy = Proxy.all("http://username:password@proxy.example.com:8080") + +client = Client(proxies=[proxy]) +``` + +Or using the credentials separately + +```python +proxy = Proxy.all( + url="http://proxy.example.com:8080", + username="username", + password="password" +) + +client = Client(proxies=[proxy]) +``` + +**SOCKS5 proxy with credentials:** + +```python +# SOCKS5 +client = Client( + proxies=[Proxy.http("socks5://username:password@127.0.0.1:1080")] +) + + +# SOCKS5h (DNS also resolved by the proxy) +client = Client( + proxies=[Proxy.http("socks5h://username:password@127.0.0.1:6152")] +) +``` + +> The difference between `socks5://` and `socks5h://` is that `socks5h` delegates DNS resolution to the proxy server, which helps avoid DNS leaks. + +--- + +### Per-request proxy with custom headers + +You can configure a proxy for a single request and attach custom headers sent to the proxy server: + +```python +import asyncio +import wreq +from wreq import Proxy + +async def main(): resp = await wreq.get( "https://httpbin.io/anything", - proxy=Proxy.all( - url="http://127.0.0.1:6152", - custom_http_headers={ - "user-agent": "wreq", - "accept": "*/*", - "accept-encoding": "gzip, deflate, br", - "x-proxy": "wreq", - }, - ), + proxies=[ + Proxy.all( + url="http://127.0.0.1:6152", + custom_http_headers={ + "user-agent": "wreq", + "accept": "*/*", + "accept-encoding": "gzip, deflate, br", + "x-proxy": "wreq", + }, + ) + ], ) print(await resp.text()) - -if __name__ == "__main__": - asyncio.run(main()) +asyncio.run(main()) ``` -### Unix Socket Proxy +> **Note:** `custom_http_headers` are headers sent *to the proxy itself*, not to the final destination server. -Using Unix sockets for local services like Docker: +--- + +## Unix Socket Proxy + +Unix sockets allow communication with local services without going through a network port. This is common when working with Docker, Podman, or other daemons that expose a socket file. ```python import asyncio import wreq from wreq import Proxy - async def main(): - # Send request via Unix socket proxy resp = await wreq.get( "http://localhost/v1.41/containers/json", - proxy=Proxy.unix("/var/run/docker.sock"), + proxies=[Proxy.unix("/var/run/docker.sock")], ) print(await resp.text()) - -if __name__ == "__main__": - asyncio.run(main()) +asyncio.run(main()) ``` + +Even though the URL says `http://localhost`, the request never touches the network. It goes directly through the socket file at the given path. + +--- + +## Choosing the right constructor + +Each constructor controls which requests are intercepted by the proxy: + +| Constructor | Intercepts | +|---|---| +| `Proxy.all(url)` | All requests (HTTP + HTTPS) | +| `Proxy.http(url)` | HTTP requests only | +| `Proxy.https(url)` | HTTPS requests only | +| `Proxy.unix(path)` | Requests via a Unix socket | From 06ac143e2472d0c213f17bacb6633f4a23441467 Mon Sep 17 00:00:00 2001 From: Marc <50042689+mrcsnv@users.noreply.github.com> Date: Tue, 14 Apr 2026 15:10:43 +0200 Subject: [PATCH 2/3] Revise proxy example in quickstart documentation Updated the proxy usage example to reflect the new Client initialization with a list of proxies. --- docs/source/getting-started/quickstart.md | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/docs/source/getting-started/quickstart.md b/docs/source/getting-started/quickstart.md index 715c59c7..0cb72772 100644 --- a/docs/source/getting-started/quickstart.md +++ b/docs/source/getting-started/quickstart.md @@ -69,13 +69,21 @@ asyncio.run(main()) ## Using Proxies +The [Proxy](../guide/proxy.md) object defines how your HTTP client routes traffic through a proxy server. +You create one using a named constructor that specifies the scope: + +- `Proxy.all(url)` — routes all traffic through the given proxy +- `Proxy.http(url)` - only intercepts HTTP requests +- `Proxy.https(url)` — only intercepts HTTPS requests + +Once created, you pass it to the `Client` and all requests will go through it automatically. + ```python import asyncio -from wreq import Client -from wreq.proxy import Proxy +from wreq import Client, Proxy async def main(): - client = Client(proxy=Proxy.all("http://proxy.example.com:8080")) + client = Client(proxies=[Proxy.all("http://proxy.example.com:8080")]) resp = await client.get("https://httpbin.org/ip") print(await resp.text()) @@ -107,4 +115,4 @@ asyncio.run(main()) ## Next Steps - See the [Examples](../guide/basic.md) for more code samples -- Explore the [API Reference](../api/wreq.md) for detailed documentation \ No newline at end of file +- Explore the [API Reference](../api/wreq.md) for detailed documentation From 6039d80d5f1ff6d9adcb1bf0ec8f80b9671aa77a Mon Sep 17 00:00:00 2001 From: Marc <50042689+mrcsnv@users.noreply.github.com> Date: Tue, 14 Apr 2026 15:12:02 +0200 Subject: [PATCH 3/3] Correct bullet point formatting in quickstart.md Fix formatting of bullet points in quickstart.md --- docs/source/getting-started/quickstart.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/getting-started/quickstart.md b/docs/source/getting-started/quickstart.md index 0cb72772..fd3b4b3c 100644 --- a/docs/source/getting-started/quickstart.md +++ b/docs/source/getting-started/quickstart.md @@ -72,9 +72,9 @@ asyncio.run(main()) The [Proxy](../guide/proxy.md) object defines how your HTTP client routes traffic through a proxy server. You create one using a named constructor that specifies the scope: -- `Proxy.all(url)` — routes all traffic through the given proxy +- `Proxy.all(url)` - routes all traffic through the given proxy - `Proxy.http(url)` - only intercepts HTTP requests -- `Proxy.https(url)` — only intercepts HTTPS requests +- `Proxy.https(url)` - only intercepts HTTPS requests Once created, you pass it to the `Client` and all requests will go through it automatically.