Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions docs/source/getting-started/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -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())

Expand Down Expand Up @@ -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
- Explore the [API Reference](../api/wreq.md) for detailed documentation
148 changes: 118 additions & 30 deletions docs/source/guide/proxy.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Comment on lines +19 to +21
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix parameter name inconsistency.

Line 21 states that per-request proxies use proxy=... (singular), but all the per-request examples in this file use proxies=[...] (plural):

  • Line 103: await wreq.get(..., proxies=[Proxy.all(...)])
  • Line 136: await wreq.get(..., proxies=[Proxy.unix(...)])

The examples suggest the correct parameter name is proxies (plural) for both client-level and per-request usage.

📝 Proposed fix
 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.
+- **Per-request** via `wreq.get(..., proxies=[...])` — overrides or sets a proxy for a single request.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
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.
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(..., proxies=[...])` — overrides or sets a proxy for a single request.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/source/guide/proxy.md` around lines 19 - 21, Update the documentation to
use the correct parameter name "proxies" (plural) for per-request usage so it
matches the examples; change the sentence that currently shows wreq.get(...,
proxy=...) to wreq.get(..., proxies=[...]) and ensure references to
Client(proxies=[...]), wreq.get(..., proxies=[Proxy.all(...)]), and
wreq.get(..., proxies=[Proxy.unix(...)]) are consistent throughout the file.


---

## 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",
},
)
],
Comment thread
mrcsnv marked this conversation as resolved.
)
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")],
Comment thread
mrcsnv marked this conversation as resolved.
)
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 |