httpcache

package module
v0.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 4, 2025 License: Apache-2.0 Imports: 11 Imported by: 1

README

httpcache

Go Reference Go Report Card Test codecov

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.

Features

  • Plug-and-Play: Drop-in replacement for http.RoundTripper with no additional configuration required.
  • RFC 9111 Compliance: Handles validation, expiration, and revalidation.
  • Cache Control: Supports all relevant HTTP cache control directives, as well as extensions like stale-while-revalidate and stale-if-error.
  • Cache Backends: Built-in support for file system and memory caches, with the ability to implement custom backends.
  • Extensible: Options for logging, transport and timeouts.
  • Debuggable: Adds a cache status header to every response.
  • Zero Dependencies: No external dependencies, pure Go implementation.

Made with VHS

Refer to _examples/app for the source code.

Quick Start

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
}

To use a cache backend, specify it with a DSN string (e.g., "fscache://" or "memcache://"). You must import the backend package (often with a blank import) to register it.

Cache Backends

Backend DSN Example Description
fscache fscache://?appname=myapp Built-in file system cache, stores responses on disk
memcache memcache:// Built-in memory cache, stores responses in memory

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 httpcache.Cache interface. This interface requires methods for storing, retrieving, and deleting cached responses. You can then register your backend by importing it in your application. See the fscache for an example implementation.

Options

Option Description Default Value
WithTransport(http.RoundTripper) Set the underlying transport http.DefaultTransport
WithSWRTimeout(time.Duration) Set the stale-while-revalidate timeout 5s
WithLogger(*slog.Logger) Set a logger for debug output slog.New(slog.DiscardHandler)

Supported Cache-Control Directives

Directive Request Response Description
max-age Maximum age for cache freshness
min-fresh Minimum freshness required
max-stale Accept response stale by up to N seconds
no-cache Must revalidate with origin before using
no-store Do not store in any cache
only-if-cached Only serve from cache, never contact origin
must-revalidate Must revalidate once stale
must-understand Require cache to understand directive
public Response may be cached, even if normally non-cacheable
stale-while-revalidate Serve stale while revalidating in background (RFC 5861)
stale-if-error Serve stale if origin returns error (RFC 5861)

Note: The private, proxy-revalidate, and s-maxage directives bear no relevance in a private client-side cache and are ignored.

Cache Status Header

Every response includes a cache status header to indicate how the response was served. The header is named X-Cache-Status and can have the following values:

Status Description
HIT Served from cache
MISS Fetched from origin
STALE Served stale from cache
REVALIDATED Revalidated with origin
BYPASS Cache bypassed
Example
X-Cache-Status: HIT

Limitations

  • 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. See RFC 9111 §3.3-3.4 for details.

License

This project is licensed under the Apache License 2.0. See the LICENSE file for details.

Documentation

Overview

Package httpcache provides an implementation of http.RoundTripper that adds transparent HTTP response caching according to RFC 9111 (HTTP Caching).

The main entry point is NewTransport, which returns an http.RoundTripper for use with http.Client. httpcache supports the required standard HTTP caching directives, as well as extension directives such as stale-while-revalidate and stale-if-error.

Example usage:

package main

import (
	"log/slog"
	"net/http"
	"time"

	"github.com/bartventer/httpcache"

	// Register a cache backend by importing the package
	_ "github.com/bartventer/httpcache/store/fscache"
)

func main() {
	dsn := "fscache://?appname=myapp" // // Example DSN for the file system cache backend
	client := &http.Client{
		Transport: httpcache.NewTransport(
			dsn,
			httpcache.WithSWRTimeout(10*time.Second),
			httpcache.WithLogger(slog.Default()),
		),
	}
}

Index

Constants

View Source
const CacheStatusHeader = internal.CacheStatusHeader
View Source
const DefaultSWRTimeout = 5 * time.Second // Default timeout for Stale-While-Revalidate

Variables

View Source
var ErrNilCache = errors.New("httpcache: cache cannot be nil")

ErrNilCache is returned when a nil cache is provided to [NewRoundTripper]. Although not recommended, it is possible to handle this error gracefully by recovering from the panic that occurs when a nil cache is passed.

Example usage:

defer func() {
	if r := recover(); r != nil {
		if err, ok := r.(error); ok && errors.Is(err, ErrNilCache) {
			// Handle the error gracefully, e.g., log it or return a default transport
			log.Println("Cache cannot be nil:", err)
			client := &http.Client{
				Transport: http.DefaultTransport, // Fallback to default transport
			}
			// Use the fallback client as needed
			_ = client
		} else {
			// Re-panic if it's not the expected error
			panic(r)
		}
	}
}()

Functions

func NewTransport

func NewTransport(dsn string, options ...Option) http.RoundTripper

NewTransport returns an http.RoundTripper that caches HTTP responses using the specified cache backend.

The backend is selected via a DSN (e.g., "memcache://", "fscache://"). Panics if the cache cannot be opened or is nil. A blank import is required to register the cache backend.

To configure the transport, you can use functional options such as WithTransport, WithSWRTimeout, and WithLogger.

Types

type Option

type Option interface {
	// contains filtered or unexported methods
}

Option is a functional option for configuring the RoundTripper.

func WithLogger

func WithLogger(logger *slog.Logger) Option

WithLogger sets the logger for debug output; default: slog.New(slog.DiscardHandler).

func WithSWRTimeout

func WithSWRTimeout(timeout time.Duration) Option

WithSWRTimeout sets the timeout for Stale-While-Revalidate requests; default: DefaultSWRTimeout.

func WithTransport

func WithTransport(transport http.RoundTripper) Option

WithTransport sets the underlying HTTP transport for making requests; default: http.DefaultTransport.

Directories

Path Synopsis
_examples
app command
testutil
Package testutil provides utility functions for testing in Go.
Package testutil provides utility functions for testing in Go.
Package store defines interfaces to be implemented by cache backends as used by the github.com/bartventer/httpcache package.
Package store defines interfaces to be implemented by cache backends as used by the github.com/bartventer/httpcache package.
acceptance
Package acceptancetest provides a suite of acceptance tests for Cache implementations.
Package acceptancetest provides a suite of acceptance tests for Cache implementations.
fscache
Package fscache implements a file system-based store.Cache.
Package fscache implements a file system-based store.Cache.
memcache
Package memcache provides an in-memory implementation of store.Cache.
Package memcache provides an in-memory implementation of store.Cache.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL