Httpcache
Standards-compliant HTTP caching transport for Go clients (RFC 9111).
Install / Use
/learn @bartventer/HttpcacheREADME
httpcache
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.
Features
- Plug-and-Play: Just swap in as your HTTP client's transport; no extra configuration needed. [^1]
- RFC 9111 Compliance: Handles validation, expiration, and revalidation (see details).
- Cache Control: Supports all required HTTP cache control directives, as well as extensions like
stale-while-revalidate,stale-if-error, andimmutable(see details). - Cache Backends: Built-in support for file system and memory caches, with the ability to implement custom backends (see Cache Backends).
- Cache Maintenance API: Optional REST endpoints for listing, retrieving, and deleting cache entries (see Cache Maintenance API).
- Extensible: Options for logging, transport and timeouts (see Options).
- Debuggable: Adds a cache status header to every response (see Cache Status Headers).
- Zero Dependencies: No external dependencies, pure Go implementation.

Demonstration of HTTP caching in action. See _examples/app for code.
Installation
To install the package, run:
go get github.com/bartventer/httpcache
Quick Start
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.
Cache Backends
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.
Custom Cache Backends
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.
Cache Maintenance API (Debug Only)
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 entry
All 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().
Options
| 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) |
Cache Status Headers
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 withgregjones/httpcache. Only set for cache hits/stale/revalidated responses.
Header Value Mapping
| 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 |
Example: Stale cache hit
HTTP/1.1 200 OK
X-Httpcache-Status: STALE
X-From-Cache: 1
Content-Type: application/json
Limitations
-
Range Requests & Partial Content: This cache does not support HTTP range requests or partial/incomplete responses (e.g., status code 206,
Range/Content-Rangeheaders). All requests with aRangeheader are bypassed, and 206 responses are not cached. For example:GET /example.txt HTTP/1.1 Host: example.com Range: bytes=0-99The above request will bypass the cache and fetch the response directly from the origin server. See RFC 9111 §3.3-3.4 for details.
RFC 9111 Compliance Matrix
| § | 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 fo
