
Company News
Socket Named Top Sales Organization by RepVue
Socket won two 2026 Reppy Awards from RepVue, ranking in the top 5% of all sales orgs. AE Alexandra Lister shares what it's like to grow a sales career here.
github.com/bartventer/httpcache
Advanced tools
httpcache is a Go package that provides a standards-compliant http.RoundTripper for transparent HTTP response caching, following RFC 9111 (HTTP Caching).
Note: This package is intended for use as a private (client-side) cache. It is not a shared or proxy cache. It is designed to be used with an HTTP client to cache responses from origin servers, improving performance and reducing load on those servers.
stale-while-revalidate, stale-if-error, and immutable (view details).
Demonstration of HTTP caching in action. See _examples/app for code.
To install the package, run:
go get github.com/bartventer/httpcache
To get started, create a new HTTP client with the httpcache transport, specifying a cache backend DSN. You'll need to register the desired cache backend before using it. Here's an example using the built-in file system cache:
package main
import (
"log/slog"
"net/http"
"time"
"github.com/bartventer/httpcache"
// Register the file system cache backend
_ "github.com/bartventer/httpcache/store/fscache"
)
func main() {
// Example DSN for the file system cache backend
dsn := "fscache://?appname=myapp"
client := &http.Client{
Transport: httpcache.NewTransport(
dsn,
httpcache.WithSWRTimeout(10*time.Second),
httpcache.WithLogger(slog.Default()),
),
}
// ... Use the client as usual
}
Note: The DSN format and options depend on the cache backend you choose. Refer to the Cache Backends section for details on available backends and their DSN formats.
The following built-in cache backends are available:
| Backend | DSN Example | Description |
|---|---|---|
fscache | fscache://?appname=myapp | File system cache, stores responses on disk. Suitable for persistent caching across restarts. Supports context cancellation, as well as optional AES-GCM encryption. |
memcache | memcache:// | In-memory cache, suitable for ephemeral caching. Does not persist across restarts. |
Consult the documentation for each backend for specific configuration options and usage details.
To implement a custom cache backend, create a type that satisfies the store/driver.Conn interface, then register it using the store.Register function. Refer to the built-in backends for examples of how to implement this interface.
A REST API is available for cache inspection and maintenance, intended for debugging and development use only. Do not expose these endpoints in production.
Endpoints:
GET /debug/httpcache — List cache keys (if supported)GET /debug/httpcache/{key} — Retrieve a cache entryDELETE /debug/httpcache/{key} — Delete a cache entryAll endpoints require a dsn query parameter to select the cache backend.
Usage Example:
import (
"net/http"
"github.com/bartventer/httpcache/store/expapi"
)
func main() {
expapi.Register()
http.ListenAndServe(":8080", nil)
}
To use a custom ServeMux, pass expapi.WithServeMux(mux) to expapi.Register().
| Option | Description | Default Value |
|---|---|---|
WithUpstream(http.RoundTripper) | Set a custom transport for upstream/origin requests | http.DefaultTransport |
WithSWRTimeout(time.Duration) | Set the stale-while-revalidate timeout | 5 * time.Second |
WithLogger(*slog.Logger) | Set a logger for debug output | slog.New(slog.DiscardHandler) |
This package sets a cache status header on every response:
X-Httpcache-Status: The primary, detailed cache status header (always set).X-From-Cache: (Legacy) Provided for compatibility with gregjones/httpcache. Only set for cache hits/stale/revalidated responses.| X-Httpcache-Status | X-From-Cache | Description |
|---|---|---|
| HIT | 1 | Served from cache |
| STALE | 1 | Served from cache but stale |
| REVALIDATED | 1 | Revalidated with origin |
| MISS | (not set) | Served from origin |
| BYPASS | (not set) | Bypassed cache, served from origin |
HTTP/1.1 200 OK
X-Httpcache-Status: STALE
X-From-Cache: 1
Content-Type: application/json
Range Requests & Partial Content:
This cache does not support HTTP range requests or partial/incomplete responses (e.g., status code 206, Range/Content-Range headers). All requests with a Range header are bypassed, and 206 responses are not cached. For example:
GET /example.txt HTTP/1.1
Host: example.com
Range: bytes=0-99
The above request will bypass the cache and fetch the response directly from the origin server. See RFC 9111 §3.3-3.4 for details.
| § | Title | Requirement | Implemented | Notes |
|---|---|---|---|---|
| 1. | Introduction | N/A | N/A | Nothing to implement |
| 2. | Overview of Cache Operation | N/A | N/A | Nothing to implement |
| 3. | Storing Responses in Caches | Required | ✔️ | Details |
| 4. | Constructing Responses from Caches | Required | ✔️ | Details |
| 5. | Field Definitions | Required | ✔️ | Details |
| 6. | Relationship to Applications and Other Caches | N/A | N/A | Nothing to implement |
| 7. | Security Considerations | N/A | N/A | Nothing to implement |
| 8. | IANA Considerations | N/A | N/A | Nothing to implement |
| 9. | References | N/A | N/A | Nothing to implement |
Legend for Requirements:
| Requirement | Description |
|---|---|
| Required | Must be implemented for RFC compliance |
| Optional | May be implemented, but not required for compliance |
| Obsolete | Directive is no longer relevant as per RFC 9111 |
| Deprecated | Directive is deprecated as per RFC 9111, but can still be implemented |
| N/A | Nothing to implement or not applicable to private caches |
| § | Title | Requirement | Implemented | Notes |
|---|---|---|---|---|
| 3.1. | Storing Header and Trailer Fields | Required | ✔️ | |
| 3.2. | Updating Stored Header Fields | Required | ✔️ | |
| 3.3. | Storing Incomplete Responses | Optional | ❌ | See Limitations |
| 3.4. | Combining Partial Content | Optional | ❌ | See Limitations |
| 3.5. | Storing Responses to Authenticated Requests | N/A | N/A | Not applicable to private client-side caches |
| § | Title | Requirement | Implemented | Notes |
|---|---|---|---|---|
| 4.1. | Calculating Cache Keys with the Vary Header Field | Required | ✔️ | |
| 4.2. | Freshness | Required | ✔️ | Details |
| § | Title | Requirement | Implemented | Notes |
|---|---|---|---|---|
| 4.2.1. | Calculating Freshness Lifetime | Required | ✔️ | |
| 4.2.2. | Calculating Heuristic Freshness | Required | ✔️ | |
| 4.2.3. | Calculating Age | Required | ✔️ | |
| 4.2.4. | Serving Stale Responses | Required | ✔️ |
| § | Title | Requirement | Implemented | Notes |
|---|---|---|---|---|
| 4.3. | Validation | Required | ✔️ | Details |
| § | Title | Requirement | Implemented | Notes |
|---|---|---|---|---|
| 4.3.1. | Sending a Validation Request | Required | ✔️ | |
| 4.3.2. | Handling Received Validation Request | N/A | N/A | Not applicable to private client-side caches |
| 4.3.3. | Handling a Validation Response | Required | ✔️ | |
| 4.3.4. | Freshening Stored Responses upon Validation | Required | ✔️ | |
| 4.3.5. | Freshening Responses with HEAD | Optional | ❌ | Pointless, rather use conditional GETs; see RFC 9110 §13.2.1 last para |
| § | Title | Requirement | Implemented | Notes |
|---|---|---|---|---|
| 4.4. | Invalidating Stored Responses | Required | ✔️ |
| § | Title | Requirement | Implemented | Notes |
|---|---|---|---|---|
| 5.1. | Age | Required | ✔️ | |
| 5.2. | Cache-Control | Required | ✔️ | Details |
| 5.3. | Expires | Required | ✔️ | |
| 5.4. | Pragma | Deprecated | ❌ | Deprecated by RFC 9111; not implemented |
| 5.5. | Warning | Obsolete | ❌ | Obsoleted by RFC 9111; not implemented |
| § | Title | Requirement | Implemented | Notes |
|---|---|---|---|---|
| 5.2.1. | Request Directives | Optional | ✔️ | Details |
| § | Title/Directive | Requirement | Implemented | Notes |
|---|---|---|---|---|
| 5.2.1.1. | max-age | Optional | ✔️ | |
| 5.2.1.2. | max-stale | Optional | ✔️ | |
| 5.2.1.3. | min-fresh | Optional | ✔️ | |
| 5.2.1.4. | no-cache | Optional | ✔️ | |
| 5.2.1.5. | no-store | Optional | ✔️ | |
| 5.2.1.6. | no-transform | Optional | ✔️ | Compliant by default - implementation never transforms content |
| 5.2.1.7. | only-if-cached | Optional | ✔️ |
| Section | Requirement | Implemented | Notes |
|---|---|---|---|
| 5.2.2. Response Directives | Required | ✔️ | Details |
| § | Title/Directive | Requirement | Implemented | Notes |
|---|---|---|---|---|
| 5.2.2.1. | max-age | Required | ✔️ | |
| 5.2.2.2. | must-revalidate | Required | ✔️ | |
| 5.2.2.3. | must-understand | Required | ✔️ | |
| 5.2.2.4. | no-cache | Required | ✔️ | Both qualified and unqualified forms supported |
| 5.2.2.5. | no-store | Required | ✔️ | |
| 5.2.2.6. | no-transform | Required | ✔️ | Compliant by default - implementation never transforms content |
| 5.2.2.7. | private | N/A | N/A | Intended for shared caches; not applicable to private caches |
| 5.2.2.8. | proxy-revalidate | N/A | N/A | Intended for shared caches; not applicable to private caches |
| 5.2.2.9. | public | Optional | ✔️ | |
| 5.2.2.10. | s-maxage | N/A | N/A | Intended for shared caches; not applicable to private caches |
| § | Title | Requirement | Implemented | Notes |
|---|---|---|---|---|
| 5.2.3. | Extension Directives | Optional | partially | Details |
The following additional cache control directives are supported, as defined in various RFCs:
| Reference | Directive | Notes |
|---|---|---|
| RFC 5861, §3 | stale-while-revalidate | Only applies to responses |
| RFC 5861, §4 | stale-if-error | Applies to both requests and responses |
| RFC 8246, §2 | immutable | Only applies to responses |
This project is licensed under the Apache License 2.0. See the LICENSE file for details.
No configuration is needed beyond the cache backend DSN. Caching is handled automatically based on HTTP headers and directives. To use a custom upstream transport, pass it with the WithUpstream option. This lets you add httpcache to your existing HTTP client with minimal changes. See Options for details. ↩
FAQs
Unknown package
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Company News
Socket won two 2026 Reppy Awards from RepVue, ranking in the top 5% of all sales orgs. AE Alexandra Lister shares what it's like to grow a sales career here.

Security News
NIST will stop enriching most CVEs under a new risk-based model, narrowing the NVD's scope as vulnerability submissions continue to surge.

Company News
/Security News
Socket is an initial recipient of OpenAI's Cybersecurity Grant Program, which commits $10M in API credits to defenders securing open source software.