Skip to content

Upstream upgrade#9

Merged
pigri merged 111 commits intomainfrom
upstream_upgrade
Mar 12, 2026
Merged

Upstream upgrade#9
pigri merged 111 commits intomainfrom
upstream_upgrade

Conversation

@pigri
Copy link

@pigri pigri commented Mar 12, 2026

No description provided.

johnhurt and others added 30 commits November 13, 2025 21:40
This commit introduces a new framework for adding implementing custom
application protocols. This enables bidirectional message streams
alongside standard HTTP flows and provides seamless proxying between
HTTP/1.1, HTTP/2, and custom protocols. This should have a zero, or
near-zero performance impact on existin HTTP/1.1 and HTTP/2 use cases.

Co-authored-by: Abhishek Aiyer <aaiyer@cloudflare.com>
Saw this in logs:

```
2025-08-16T11:11:42.859488Z ERROR ThreadId(36) pingora_proxy: /usr/local/cargo/registry/src/index.crates.~~~cf8c6b5b557f/pingora-~~~.5.0/src/lib.rs:148: Fail to proxy: Downstream InvalidHTTPHeader context: buf: \u{16}\u{3}\u{1}\u{0}\u{fffd}\u{1}\u{0}\u{0}\u{fffd}\u{3}\u{3}\u{fffd}\u{17}\u{b}0\u{fffd}!\u{fffd}T\u{fffd}\u{fffd}\u{b}\u{fffd}\u{1e}\u{fffd}\u{fffd}\u{fffd}i\u{2e4}\u{fffd}\u{fffd}\u{fffd}\u{fffd}\u{fffd}BD\u{12}k m\u{fffd}&:\u{fffd}\u{fffd}\u{fffd}\u{fffd}\u{fffd}\u{14}\u{fffd}]\u{fffd}?\u{7a4}a\u{fffd}\u{1f}\u{fffd}m\u{fffd}\u{1c}L\u{c}I\u{fffd}\u{14}N\u{fffd}\u{fffd}\u{0}&\u{328}\u{329}\u{fffd}/\u{fffd}0\u{fffd}+\u{fffd},\u{fffd}\u{13}\u{fffd}\t\u{fffd}\u{14}\u{fffd}\n\u{0}\u{fffd}\u{0}\u{fffd}\u{0}/\u{0}5\u{fffd}\u{12}\u{0}\n\u{13}\u{3}\u{13}\u{1}\u{13}\u{2}\u{1}\u{0}\u{0}{\u{0}\u{5}\u{0}\u{5}\u{1}\u{0}\u{0}\u{0}\u{0}\u{0}\n\u{0}\n\u{0}\u{8}\u{0}\u{1d}\u{0}\u{17}\u{0}\u{18}\u{0}\u{19}\u{0}\u{b}\u{0}\u{2}\u{1}\u{0}\u{0}\r\u{0}\u{1a}\u{0}\u{18}\u{8}\u{4}\u{4}\u{3}\u{8}\u{7}\u{8}\u{5}\u{8}\u{6}\u{4}\u{1}\u{5}\u{1}\u{6}\u{1}\u{5}\u{3}\u{6}\u{3}\u{2}\u{1}\u{2}\u{3}\u{fffd}\u{1}\u{0}\u{1}\u{0}\u{0}\u{12}\u{0}\u{0}\u{0}+\u{0}\t\u{8}\u{3}\u{4}\u{3}\u{3}\u{3}\u{2}\u{3}\u{1}\u{0}3\u{0}&\u{0}$\u{0}\u{1d}\u{0} \u{e}\u{fffd}\u{fffd}Q\u{f}\u{fffd}\u{fffd}\u{fffd}\u{79bc}:\u{fffd}\r\u{fffd}\u{fffd}\\\u{fffd}\u{c}\u{fffd}E\u{7f}\u{fffd}b\u{fffd}\u{fffd}\u{fffd}H\u{fffd}HHz cause: invalid token
```

There are two issues here:
- it is too verbose
- it is lossy (which might help if we need to actually decode these bytes)

`bstr` crate is designed to print such strings. It is popular crate
developed by a person known in Rust community, so this dependency
is fine.

Includes-commit: 5fcc52e
Replicated-from: cloudflare#683
Co-authored-by: Matthew Gumport <mbg@cloudflare.com>
Previously the downstream error was only ignored once ServeFromCache had
miss enabled (when partial read support exists and we have a confirmed
miss). The proxy state machines now also ignore errors prior to the
header being received.
This enables enriching lock wait spans for user-defined CacheKeyLock
implementations.
Additionally a max_size param is added to the increment_weight APIs for
eviction manager consumption.
httparse itself does not treat the terminating chunk (0 + CRLF) any
differently when parsing its chunk size, and the body reader does not
validate the following CRLF required to close the body.

Additionally, that current parsing scheme will not consider trailers
before the end CRLF. Now the trailers are considered but simply
discarded. The CRLFs between the trailers (and now, the CRLFs after the
body payloads) are validated, however.
---
chore: address clippy::single_match
---
Fix connection filter inheritance for endpoints added after filter setup

Previously, endpoints added to Listeners after set_connection_filter() was
called would not inherit the filter. This change stores the filter in the
Listeners struct and applies it to all subsequently added endpoints.

- Store connection filter in Listeners for future endpoints
- Apply stored filter when adding new endpoints via add_endpoint()
- Update Service to propagate filter to its Listeners
- Add test to verify filter inheritance behavior
- Add example demonstrating connection filter usage
---
chore: no unicode
---
feat: add connection_filter feature for early TCP-level connection filtering
---
feat: add connection_filter feature flag to main pingora crate
---
fix: clean up connection_filter implementation and remove debug code
---
fix: clippy unused import
---
fix: use expect() for consistency and document performance choice in filter
---
Merge remote-tracking branch 'upstream/main' into feat/connection-filter
---
fix: removed unused

Includes-commit: 1b8bd90
Includes-commit: 69e94d0
Includes-commit: 755c9e5
Includes-commit: 81d5962
Includes-commit: 9b891bc
Includes-commit: 9fd7fb9
Includes-commit: a04da3b
Includes-commit: d353953
Includes-commit: d919e10
Includes-commit: ee7fac4
Includes-commit: f9d9f4c
Replicated-from: cloudflare#671
While reader timeouts should still attempt to fetch without locking,
writer age timeouts can cause thundering herds if they force existing
readers to give up.
Cacheable responses http versions are already internally set to H1, but
there were cases in which HTTP/1.0 origins could have HTTP/1.0 version
responses proxied on miss with transfer-encoding which is not RFC
compliant and rejected by some major clients.
duke8253 and others added 28 commits March 2, 2026 16:36
RFC9112 is now extra explicit about the close delimiting applying
exclusively to response messages for HTTP/1.0. Also disables reuse
explicitly when close delimiting on the response side as
defense-in-depth that shouldn't have behavioral diff.
The upgrade body mode changes also should be applied to subrequests
though upgrade and websockets are still highly experimental for them.
If a content-length is present RFC9112 indicates we must reject invalid
forms of that content-length header. This eliminates situations where we
might be dealing with ambiguous request framing.
Custom sessions need to report their upgrade state to the
proxy framework. Previously, Session::is_upgrade_req() and
Session::was_upgraded() always returned false for Custom sessions,
which broke WebSocket upgrade handling when using custom protocols.

This change:
- Adds is_upgrade_req() and was_upgraded() methods to the custom
  Session trait with default implementations returning false
- Updates the main Session enum to delegate to the custom session's
  implementation instead of returning false
This can be enabled via server options. Since CONNECT changes the
request-response flow separate from HTTP much like upgrade requests but
is currently unsupported, these requests will be automatically rejected
by default.
When a custom protocol is shutdown, it is passed
a numeric code. This should be 0 to indicate an
explicit shutdown rather than any other transport
error.
Anyone using caching must must now implement cache_key_callback themselves. This
forces an explicit decision about what belongs in the cache key for anyone using
thet trait for caching rather than providing an unsafe default that does not
support web standards.
If the body is not init when upgraded, there was an issue where the body
might be improperly ended early and the conn simply closed.
Rejecting bad upstream content-length by default to avoid forwarding
ambiguously framed messages. An option still exists to allow this
in the peer options, if needed, and treat these responses as
close-delimited though this is non-RFC-compliant.

The content-length is now also removed on the response if
transfer-encoding is present, per RFC.
…ket` impl

The `#[cfg(windows)] impl AsRawSocket for RawStream` was missing a match
arm for the `RawStream::Virtual(_)` variant, causing a compilation error
(E0004: non-exhaustive patterns) on Windows targets.

The `Virtual` variant is not gated by any `#[cfg]` attribute and exists
on all platforms, but the Windows `AsRawSocket` implementation only
matched `RawStream::Tcp(s)`.

This fix adds the missing arm, returning `!0` (INVALID_SOCKET) for
virtual streams, consistent with the Unix `AsRawFd` implementation
which returns `-1` for the same variant.

Co-authored-by: Cursor <cursoragent@cursor.com>
Includes-commit: 6da94f9
Replicated-from: cloudflare#809
The peer option wasn't always being applied when used with other
connectors like v2. Also clarify this is to support legacy behavior and
may be removed in the future.
---
Merge branch 'cloudflare:main' into fix-socket-perms

Includes-commit: 7a748e7
Includes-commit: fdc2027
Replicated-from: cloudflare#810
`parse_range_header` was returning `RangeType::None` for the input
`"bytes="` (the bytes= prefix with no range-specs after it). Per RFC 9110
14.1.2, `"bytes="` is syntactically a range request with zero satisfiable
range-specs, so the correct response is 416 Range Not Satisfiable.

Added an early check for an empty/whitespace-only range-set after the
`bytes=` prefix, returning `RangeType::Invalid` instead of falling
through to the regex loop.
This removes {transfer,content}-encoding headers from 416 resonses. This
mirrors what to_304() in conditional_filter.rs already does for 304 Not
Modified responses.
Resolves conflicts in:
- pingora-core/Cargo.toml: keep proxy-protocol dep + upstream lru workspace change + daggy
- pingora-core/src/listeners/tls/boringssl_openssl/mod.rs: keep GetSocketDigest + AlpnError imports
- pingora-core/src/server/mod.rs: keep proxy protocol functions + upstream service dependency system

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@pigri pigri merged commit e82e068 into main Mar 12, 2026
4 checks passed
@pigri pigri deleted the upstream_upgrade branch March 12, 2026 13:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.