Package httpcache provides an http.RoundTripper implementation that works as a mostly RFC 9111 (HTTP Caching) compliant cache for HTTP responses. It improves application performance by reducing redundant HTTP requests and supports various backends for use cases such as API caching, web scraping, and microservices.
RFC Compliance: This implementation follows RFC 9111 (2022), which obsoletes RFC 7234 (2014). See the compliance features for details on supported directives and behaviors.
Note: This is a maintained fork of gregjones/httpcache, which is no longer actively maintained. This fork aims to modernize the codebase while maintaining backward compatibility, fix bugs, and add new features.
- API Caching: Reduce latency and server load by caching API responses.
- Web Scraping: Avoid repeated requests to the same endpoints.
- Microservices: Cache responses between services for better performance.
- Web Applications: Improve user experience by caching dynamic content.
- Resource Caching: Store static or frequently accessed resources locally.
- β
RFC 9111 Compliant (~95% compliance) - Implements HTTP Caching standard (obsoletes RFC 7234)
- β Age header calculation with full Section 4.2.3 algorithm (request_time, response_time, response_delay tracking)
- β Age header validation per Section 5.1 (handles multiple values, invalid values with logging)
- β Cache-Control directive validation per Section 4.2.1 (duplicate detection, conflict resolution, value validation)
- β Warning headers for stale responses (Section 5.5 - deprecated but supported for compatibility)
- β must-revalidate directive enforcement (Section 5.2.2.1)
- β Pragma: no-cache support (Section 5.4 - HTTP/1.0 backward compatibility)
- β Cache invalidation on unsafe methods (Section 4.4)
- β Content-Location and Location header invalidation (Section 4.4)
- β Same-origin policy enforcement for cache invalidation
- β Cache-Control: private directive support (Section 5.2.2.6)
- β Cache-Control: must-understand directive support (Section 5.2.2.3)
- β Vary header matching per Section 4.1 (wildcard, whitespace normalization, case-insensitive)
- β Vary header separation - Optional separate cache entries for response variants (Section 4.1)
- β Authorization header handling per Section 3.5 (secure caching in shared caches)
- β Multiple Backends - Memory, Disk, Redis, LevelDB, Memcache, PostgreSQL, MongoDB, NATS K/V, Hazelcast, Cloud Storage (S3/GCS/Azure)
- β Multi-Tier Caching - Combine multiple backends with automatic fallback and promotion
- β Compression Wrapper - Automatic Gzip, Brotli, or Snappy compression for cached data
- β Security Wrapper - Optional SHA-256 key hashing and AES-256 encryption
- β Thread-Safe - Safe for concurrent use
- β Zero Dependencies - Core package uses only Go standard library
- β
Easy Integration - Drop-in replacement for
http.Client - β ETag & Validation - Automatic cache revalidation
- β Stale-If-Error - Resilient caching with RFC 5861 support
- β Stale-While-Revalidate - Async cache updates for better performance (RFC 5861)
- β Configurable Cache Mode - Use as private cache (default) or shared/public cache
package main
import (
"fmt"
"io"
"net/http"
"github.com/sandrolain/httpcache"
)
func main() {
// Create a cached HTTP client
transport := httpcache.NewMemoryCacheTransport()
client := transport.Client()
// Make requests - second request will be cached!
resp, _ := client.Get("https://example.com")
io.Copy(io.Discard, resp.Body)
resp.Body.Close()
// Check if response came from cache
if resp.Header.Get(httpcache.XFromCache) == "1" {
fmt.Println("Response was cached!")
}
}go get github.com/sandrolain/httpcache- Cache Backends - Choose and configure storage backends (Memory, Redis, PostgreSQL, etc.)
- How It Works - RFC 7234 implementation details, cache headers, and detecting cache hits
- Advanced Features - Transport configuration, stale-if-error, cache key headers, custom cache control
- Security Considerations - Multi-user applications, secure cache wrapper, best practices
- Monitoring with Prometheus - Optional metrics integration for production monitoring
Getting Started:
- Installation (this page)
- Quick Start (this page)
- Cache Backends - See all backend examples
Common Tasks:
- Detecting cache hits
- User-specific caching
- Authorization header handling
- Securing sensitive data
- Monitoring performance
Advanced Topics:
- RFC 9111 compliance
- Stale-while-revalidate
- Multi-tier caching strategies
- Compression wrapper - Gzip, Brotli, Snappy compression
- Custom cache implementation
- Multi-user considerations
See the examples/ directory for complete, runnable examples:
- Basic - Simple in-memory caching
- Disk Cache - Persistent filesystem cache
- Redis - Distributed caching with Redis
- LevelDB - High-performance persistent cache
- PostgreSQL - SQL-based persistent cache
- NATS K/V - NATS JetStream Key/Value cache
- Hazelcast - Enterprise distributed cache
- FreeCache - High-performance in-memory with zero GC
- Security Best Practices - Secure cache with encryption and key hashing
- Compress Cache - Automatic Gzip/Brotli/Snappy compression
- Multi-Tier Cache - Multi-tiered caching with automatic fallback and promotion
- Custom Backend - Build your own cache backend
- Prometheus Metrics - Monitoring cache performance
- Cache Key Headers - User-specific caching with headers
Each example includes:
- Complete working code
- Detailed README
- Use case explanations
- Best practices
IsPublicCache: true), responses with the Cache-Control: private directive are not cached.
Default Behavior: By default, httpcache operates as a private cache, which allows caching of responses marked as private.
Public Cache Mode: When IsPublicCache is set to true, the cache behaves as a shared cache and respects the private directive by not caching such responses.
See Security Considerations and Advanced Features - Private vs Public Cache for details.
IsPublicCache: true), requests with an Authorization header are NOT cached unless the response contains one of these directives:
Cache-Control: publicCache-Control: must-revalidateCache-Control: s-maxage=<seconds>
This implements RFC 9111 Section 3.5 to prevent unauthorized access to cached authenticated responses in shared caches.
Default Behavior: Private caches (default) can cache Authorization responses without restrictions.
Shared Cache Mode: Requires explicit server permission via the directives above. Additionally, use CacheKeyHeaders to separate cache entries per user:
transport.IsPublicCache = true
transport.CacheKeyHeaders = []string{"Authorization"} // Separate cache per userSee Authorization Header and Shared Caches for detailed examples and security considerations.
- Memory cache: ~100ns per operation
- Disk cache: ~1-5ms per operation (depends on filesystem)
- Redis cache: ~1-3ms per operation (network latency dependent)
- Overhead vs no-cache: < 5% for cache hits
Benchmarks are available in each backend's *_bench_test.go file.
# Run all tests
go test ./...
# Run with coverage
go test -cover ./...
# Run integration tests (requires Docker)
go test -tags=integration ./...
# Run benchmarks
go test -bench=. ./...Contributions are welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes with tests
- Run
golangci-lint runandgovulncheck ./... - Commit your changes (
git commit -m 'feat: add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is a fork of gregjones/httpcache by Greg Jones, which was archived in 2023. We're grateful for the original work and continue its development with modern Go practices.
Additional acknowledgments:
- RFC 9111 - HTTP Caching (obsoletes RFC 7234)
- RFC 7234 - HTTP Caching (obsoleted by RFC 9111, still referenced for historical context)
- RFC 5861 - HTTP Cache-Control Extensions for Stale Content
- All contributors to the original and forked projects
MIT License - see LICENSE.txt for details.
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Documentation: This README and the docs/ directory
- Examples: See examples/ for practical use cases
