# _proxy

URL: /pounce/api/_proxy/
Section: api
Description: Proxy header validation — extract real client info from trusted reverse proxies.

When ``trusted_hosts`` is configured, X-Forwarded-For/Proto/Host headers are
honoured **only** if the direct peer IP is in the trusted set.  When no trusted
hosts are configured, forwarded headers are stripped to prevent spoofing.

RFC 7239 defines a formal ``Forwarded`` header, but the ``X-Forwarded-*``
family remains the de-facto standard used by nginx, Caddy, AWS ALB, Cloudflare,
and virtually every reverse proxy in production.

---

> For a complete page index, fetch /pounce/llms.txt.

Open LLM text
(/pounce/api/_proxy/index.txt)

Share with AI

Ask Claude
(https://claude.ai/new?q=Please%20help%20me%20understand%20this%20documentation%3A%20%2Fpounce%2Fapi%2F_proxy%2Findex.txt)

Ask ChatGPT
(https://chatgpt.com/?q=Please%20help%20me%20understand%20this%20documentation%3A%20%2Fpounce%2Fapi%2F_proxy%2Findex.txt)

Ask Gemini
(https://gemini.google.com/app?q=Please%20help%20me%20understand%20this%20documentation%3A%20%2Fpounce%2Fapi%2F_proxy%2Findex.txt)

Ask Copilot
(https://copilot.microsoft.com/?q=Please%20help%20me%20understand%20this%20documentation%3A%20%2Fpounce%2Fapi%2F_proxy%2Findex.txt)

Module

#
`_proxy`

Proxy header validation — extract real client info from trusted reverse proxies.

When`trusted_hosts`is configured, X-Forwarded-For/Proto/Host headers are
honoured only if the direct peer IP is in the trusted set. When no trusted
hosts are configured, forwarded headers are stripped to prevent spoofing.

RFC 7239 defines a formal`Forwarded` header, but the `X-Forwarded-*`
family remains the de-facto standard used by nginx, Caddy, AWS ALB, Cloudflare,
and virtually every reverse proxy in production.

5Functions

## Functions

`apply_proxy_headers`

3

`dict[str, Any]`

▼

Rewrite ASGI scope fields using proxy headers from a trusted peer.

**When the …

`def apply_proxy_headers(scope: dict[str, Any], *, trusted_hosts: frozenset[str], trusted_hops: int = 1) -> dict[str, Any]`

Rewrite ASGI scope fields using proxy headers from a trusted peer.

When the direct peer is trusted:

- `client` is overwritten with the client IP from `X-Forwarded-For`,
selected`trusted_hops`positions from the RIGHT of the chain so a
client-supplied (leftmost) value cannot spoof the perceived client IP

- `scheme` is overwritten from `X-Forwarded-Proto`

- `server` (/pounce/api/server/) host is overwritten from `X-Forwarded-Host`

- `Host` is rewritten from `X-Forwarded-Host`for downstream routing

When the direct peer is not trusted (or`trusted_hosts`is empty),
all`X-Forwarded-*`headers are stripped from the scope to prevent
downstream apps from trusting spoofed values.

##### Parameters

Name
Type
Description

`scope`
`dict[str, Any]`

Mutable ASGI scope dict (modified in place and returned).

`trusted_hosts`
`frozenset[str]`

Tuple of trusted peer IPs/hostnames. The wildcard`"*"`trusts all peers (use only behind a known proxy layer).

`trusted_hops`
`int`

Number of trusted reverse-proxy hops in front of pounce. The client IP is taken this many positions from the RIGHT of`X-Forwarded-For` (each trusted proxy appends the peer it saw), falling back to the direct peer when the chain is shorter. Default `1`matches a single trusted proxy.

Default:`1`

##### Returns

`dict[str, Any]`

`_select_forwarded_for`

2

`str`

▼

Select the real client IP from an X-Forwarded-For chain by hop count.

Each tru…

`def _select_forwarded_for(forwarded_for: bytes, trusted_hops: int) -> str`

Select the real client IP from an X-Forwarded-For chain by hop count.

Each trusted reverse proxy appends the peer it observed to the right of the
chain, so with`trusted_hops`trusted proxies the real client is the
entry`trusted_hops`positions from the RIGHT. When the chain is shorter
than the configured hop count (e.g. a direct connection, or fewer real
proxies than configured), fall back to the leftmost (oldest) entry.

Returns an empty string when no usable address is present.

##### Parameters

Name
Type
Description

`forwarded_for`
`bytes`

`trusted_hops`
`int`

##### Returns

`str`

`_split_host_port`

2

`tuple[str, int]`

▼

Split a Host-style value into an ASGI server tuple.

`def _split_host_port(host: str, default_port: int) -> tuple[str, int]`

##### Parameters

Name
Type
Description

`host`
`str`

`default_port`
`int`

##### Returns

`tuple[str, int]`

`_replace_header`

3

`list[tuple[bytes, bytes]…`

▼

Replace the first header named *name*, or append it if missing.

`def _replace_header(headers: list[list[bytes]], name: bytes, value: bytes) -> list[tuple[bytes, bytes] | list[bytes]]`

##### Parameters

Name
Type
Description

`headers`
`list[list[bytes]]`

`name`
`bytes`

`value`
`bytes`

##### Returns

`list[tuple[bytes, bytes] | list[bytes]]`

`_strip_forwarded_headers`

1

`None`

▼

Remove all X-Forwarded-* headers from an ASGI scope.

Prevents untrusted client…

`def _strip_forwarded_headers(scope: dict[str, Any]) -> None`

Remove all X-Forwarded-* headers from an ASGI scope.

Prevents untrusted clients from injecting proxy headers that
downstream ASGI apps might naively trust.

##### Parameters

Name
Type
Description

`scope`
`dict[str, Any]`
