feat(cache): support conditional requests on Cache.Open and Stat#344
Merged
Conversation
Unify conditional-request handling into a single option set shared by the client wire protocol, the cache backends, and the server handlers. - client: replace the http.Request-based RequestOption with an inspectable RequestOptions struct (IfMatch/IfNoneMatch) plus Check(etag) evaluation, so non-HTTP backends can evaluate preconditions locally. - cache: Cache.Open/Stat accept variadic Option args (alias of the client type). Disk/Memory/S3 short-circuit with ErrNotModified/ErrPreconditionFailed before reading the body; Remote forwards to upstream; Tiered treats the sentinels as definitive. - httputil: matching logic moves to client; ServeCacheHit/ServeCacheStat now serve the Open/Stat outcome, mapping sentinels to 304/412. - handlers: apiv1 and the generic caching handler push request conditionals down into Open/Stat. This establishes the option plumbing for forthcoming Range/If-Range support. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Summary
Unifies conditional-request handling into a single option set shared by the client wire protocol, the cache backends, and the server handlers. Previously
If-Match/If-None-Matchwere only evaluated at the HTTP layer (httputil.ServeCacheHit), andCache.Open/Stathad no way to express preconditions — so theRemotetier couldn't forward them upstream and backends always read the body before a 304/412 could be decided.This pushes precondition evaluation down into the cache, establishing the option plumbing for forthcoming Range / If-Range support.
Changes
client: replace thehttp.Request-basedRequestOptionwith an inspectableRequestOptionsstruct (IfMatch/IfNoneMatch) plus aCheck(etag)evaluator, so non-HTTP backends can evaluate preconditions locally. The matching logic (etagListMatches) moves here fromhttputil.internal/cache:Cache.Open/Stataccept variadicOptionargs (an idiomatic alias ofclient.RequestOption).Disk/Memory/S3short-circuit withErrNotModified/ErrPreconditionFailedbefore reading the body;Remoteforwards opts to upstream (zero translation — same type);Tieredtreats the sentinels as definitive (no backfill, headers preserved for 304).internal/httputil:ServeCacheHit/ServeCacheStatnow serve theOpen/Statoutcome, mapping sentinels to 304/412;CheckConditionalsdelegates to the unifiedclientlogic (still used by the git snapshot path).apiv1and the generic caching handler parse request conditionals and push them intoOpen/Stat.Note on S3
S3's native conditional options (
SetMatchETagetc.) match against S3's object ETag, but cachew advertises a SHA256 content-hash ETag stored in the companion.metaobject — a different value. So preconditions are evaluated locally against the stored ETag rather than delegated to S3.Tests
httputil/conditional_test.gofor the outcome-based serve helpers.Conditionalcase to the shared cache suite, exercisingIf-Match/If-None-MatchonOpenandStatacross all backends (includingRemoteend-to-end).🤖 Generated with Claude Code