Repository navigation
Sync internal, 2026-10-16 - #1052
Merged
drcaramelsyrup merged 24 commits intoOct 19, 2026
Merged
drcaramelsyrup merged 24 commits into
drcaramelsyrup merged 24 commits into
Conversation
Synchronize request completion after processing upstream responses, preventing completed upgraded sessions from being polled again. Preserve normal HTTP post-body validation and cover both behaviors with regression tests.
HTTP/1 response parsing rejects spaces before header colons and obsolete line folding by default while retaining backend-defined malformed-line behavior. Callers can opt into legacy syntax or different field counts with ResponseParserConfig; connector, cache-put, and cached-header parsing are configured independently.
Keep reset watching active for custom sessions after an upgraded request reaches EOF, while preserving completed-body suppression for HTTP/1 and subrequest sessions. Expose post-upgrade polling through the session abstraction and leave idle-result validation to custom session implementations. Add regression coverage proving a reset terminates the relay without finishing or writing the request twice.
Expose an indexed-lookup with a callback so callers can validate stored entries by key without a scan or cloning data.
Every test process that starts the mock origin stops the previous openresty and starts a new one. The old instance keeps its listen ports until it has exited, so the new one could fail to bind while the readiness probe was still answered by the old one, and later requests found no listener. Wait for the old process to exit and start again if the new one exits before listening. The downstream-bail cache test also now bounds the lock wait by the body time instead of a 100 ms window. Advance the sync cursor past the reconciled revisions whose changes are already represented in this branch. The next source change is tracked by public PR #915.
The async `certificate_callback` only receives `&mut SslRef`, with no handle to the underlying connection. Applications that select or forge a leaf per connection sometimes need connection-level context that is only reachable from the socket fd, which is unavailable at certificate-selection time. `handshake_with_callback` already holds the stream when it pauses the handshake to invoke the callback, so capture the stream's fd and stash it on the SSL via `ex_data` just before the call. Add `set_downstream_fd` / `get_downstream_fd` helpers to the ext module of both openssl-derived backends -- the shared `boringssl_openssl` server path compiles against either, so both must carry the helper. The fd is stored as the same platform-conditional type as pingora-core's `UniqueIDType` (`RawFd` on unix, socket handle on Windows), so the call site passes `io.id()` through with no cast or truncation. No public trait signatures change; the rustls and s2n backends are untouched. Includes-commit: 9371d2b Replicated-from: #915
…opt-in Add an application opt-in for handling downstream disconnects during cache fills. Once enabled, the proxy reports abandonment only while a fill can produce an entry and before the response is complete, stops writing to the abandoned downstream, and lets the fill finish. Applications can release writer demand through the new hook. Keep default behavior unchanged and retry only after a completely framed request body, while caching remains enabled and no writer is active. Include compatibility coverage and remove the unused HTTP/1 abandonment marker.
Allow an opted-in application to cancel an abandoned cache fill once no readers remain. Add a cancellation watcher to miss handling, observe it across HTTP/1, HTTP/2, and custom upstream paths, process already accepted tasks, and classify cancellation for cache disablement and lock release. Keep cancellation disabled unless the application opts in, preserve connected-request handling, and fail readers when MemCache writers are dropped. Install shared test certificates atomically.
A streaming cache hit can wait on its storage indefinitely without reading its client, so a client that left kept the hit and its storage reader until a response write failed. For a request that opts in through ProxyHttp::should_handle_downstream_abandonment, a hit now watches its client while its cached body read waits, until its response is complete: an HTTP/2 client from the start, since waiting on its stream reads nothing, and any other client if its request body is complete when the hit starts. A client that closes or resets its connection, or resets its HTTP/2 stream, ends the hit and releases the reader. With abort_on_close disabled, a half-closed client keeps its response. The pending storage read is kept across client events, so a read that is not cancel-safe is not lost. The watch is the regular idle read, read_body_or_idle, so an HTTP/1 next request sent during the hit follows the connection's pipelining policy, as in the regular proxy loops. With pipelining disabled, it ends the hit with ConnectError and the connection is closed, where without the opt-in the hit never reads it and the connection is reused for it. With pipelining enabled, its first byte is kept for the next session. The watch stops once the response is complete, as ServerSession::is_response_complete reports it, so a next request sent after a complete Content-Length response stays unread even while the cache reader has yet to return the end of the body, and the connection is reused for it, as without the opt-in. The hit never reads the request body. An HTTP/1 or custom client whose request body is not complete when the hit starts is not watched, as without the opt-in, since its idle read would take a byte of that body. An HTTP/2 request whose END_STREAM arrives on a separate empty DATA frame is watched, since its stream wait reads nothing. The hit loop offers a hit to suppress_error_log before logging it only when the watch ended it because its client left, judged by the same error types as the miss loops: a closed connection, a read error or an HTTP/2 error. A client that sent its next request early is still connected, so that ConnectError, like any other failed hit, logs exactly as without the opt-in. A stale-if-error hit keeps that path's logging. Without the opt-in the hit loop is unchanged and never reads its client.
Watch the downstream during subrequest pipe waits after its request body is complete, so client disconnects cancel the pipe. Respect HTTP/1 pipelining and half-close behavior, retain pending storage reads across client events, and stop watching once the response is delivered. Make cancellation interrupt upstream pacing delays after abandonment while preserving accepted-task processing and the bounded cancellation drain, so a fully received response can still commit. Cover long body pauses, pending cancellation, normal pacing, and complete-response handling.
Add LRU operations that check an entry and then update, admit, remove or evict it under one shard lock, plus an atomic two-key mutation, so callers can validate identity and move weight without racing. Add a bounded selection of the least-recently-used eligible entry, and count an eviction only when the selected entry is finally removed.
Co-authored-by: Song Hiếu Trần <songhieu2516@gmail.com>
…ht updates Storage that corrects cache weights out of band, for example from a background size scan, needs a finished write's admission or weight update to land before it measures that write. Both finish paths now prepare a MissCompletion, which carries the entry, its freshness, the eviction manager, the storage and trace handles, and the runtime that purges evicted entries, before they consume the miss handler, and pass it to HandleMiss::finish_with_eviction. The default calls finish(), then completes the accounting with no await in between, so existing storage is unaffected. Storage that overrides it can move the completion into the worker that finishes the write and complete it there, so the accounting has one owner even after the caller's future is dropped. complete() returns a MissCompleted receipt that nothing else can create, and a successful finish_with_eviction must return it, so an override cannot report success without applying its completion. Failed writes drop the completion and return their error. Wrapping miss handlers forward the method. pingora-lru gains set_weight_if_unchanged, which replaces an entry's weight only while it still equals an expected value, without admitting, promoting or evicting. Every update to an existing entry's weight now applies one net delta to the global weight, so weight() never reports a total that no entry state ever had.
Atomic counter increments wrap on overflow, but the return-value calculation used ordinary addition and panicked with overflow checks enabled. Use wrapping_add to preserve the documented overflow behavior, and test both overflow directions. --- style(cache): align block comment for nightly rustfmt Includes-commit: 0ec7c48 Includes-commit: b50ea59 Replicated-from: #1041
When an upstream backend returns response headers containing non-UTF-8 bytes (e.g. ISO-8859-1 encoding or binary residue), 'str::from_utf8().unwrap()' in 'read_response_task' causes a panic. Replace 'str::from_utf8(...).unwrap()' with 'String::from_utf8_lossy(...)' so raw response header bytes are logged safely without risking process panics. Closes #1023 --- style: fix block comment closing for nightly rustfmt Includes-commit: 13ae58a Includes-commit: 4047c4d Replicated-from: #1039
Unit tests only, no library change: conditional revalidation header, Vary value in the variance key, inclusive serve-stale window end, uncacheable responses releasing waiting readers, case-insensitive request-target scheme, remove_header dropping the case-preserved name, and repeated headers surviving header-serde round trips. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Includes-commit: 924b472 Replicated-from: #1036
RUSTSEC-2026-0346 and RUSTSEC-2026-0349 flag rustls 0.21.12, which comes in through hyper-rustls 0.24 on the same legacy aws-sdk-s3 chain as the rustls-webpki advisories already ignored here. There is no 0.21.x backport (patched >= 0.23.46), and rustls 0.23 already resolves to 0.23.46.
Signed-off-by: Shane Utt <shaneutt@linux.com>
The action's master branch no longer exists, so the scheduled audit fails before it runs. v2.0.0 keeps the same token input.
pingora-runtime's dial9 feature depends on the metrique crates only to pin versions that Dial9 leaves open, so cargo machete reports them as unused. Add them to its ignore list in the CI checkout before it runs.
zaidoon1
approved these changes
Oct 17, 2026
duke8253
approved these changes
Oct 17, 2026
gumpt
approved these changes
Oct 19, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.