Honey is an http cache and proxy.
In the event of a cache miss, It multiplexes requests to the same URL into a single request, and once the response has been received, writes it to all requesters, and adds it to the cache.
It will set an Etag on responses, and respond with an HTTP 304 Not Modified in the event that the If-None-Match header matches the Etag.
If will not cache responses that contain the no-store Cache-Control directive
It will always fetch fresh resources if the no-cache Cache-Control directive, or if Pragma: no-cache, is set in the request
backend, err := url.Parse("https://www.example.com")
if err != nil {
panic(err)
}
cacher := cache.NewDefaultCacher()
// adding site_lang_id cookie to the default
// cacher will allow it through the cache
cacher.AddAllowedCookie("site_lang_id")
fetcher := fetch.Fetch(cacher, fetch.Forwarder(cacher), backend)
http.ListenAndServe(":8080", fetcher)
-
Handle
stale-if-error- Add unit tests
- Configurable Site-wide (whether to respect it if present, or whether to always act as if this header were present)
- Configurable Per route
- Send cached response with a
Warningheader if the backend gives an error after clearing the cache.
-
Implement configuration via TOML file (honey.toml?)
-
Come up with a way to mark certain routes/files as
immutable -
Web UI to configure / clear cache and view metrics
-
Minify html, js, css before cacheing
- Implement it
- Make this configurable (whether to do it, site wide and per route)
-
Canonicalize popular JavaScript libraries that can be replaced with ones hosted for free by a JavaScript library hosting service
- Implement it
- Make this configurable (whether to do it, site wide and per route)
-
Use http/2 push to push assets if request doesn't have an If-None-Match header
- Implement it
- Make this configurable (whether to do it, site wide and per route)
-
Rewrite static assets to cookieless subdomain
-
Combine all google-font requests into a single one
-
Implement other cache backends
-
In Memory
-
File
-
Memcached
-
Redis
-
BoltDB
-
Brotli compress if requester supports it
-
Implement it
-
Make this configurable (whether to do it, site wide and per route)
-
-
Implement offline cache
- Implement it
- Make this configurable (whether to do it, site wide and per route)
-
Automatically fix mixed-content https issues
- Implement it
- Make this configurable (whether to do it, site wide and per route)
-
Prevent hotlinking of images
- Implement it
- Make this configurable (whether to do it, site wide and per route)
-
Letsencypt SSL termination
-
Set
Last-Modifiedheader on response to the cached time if it is not already on the backend response.- Configurable Site-wide
- Configurable Per route
-
Handle
If-Modified-SinceandIf-Unmodified-Since -
If cache miss, but after refresh Etag matches, send 304 Response
-
Handle
only-if-cachedCache-Control directive -
Validate response or send to backend if
must-revalidateorproxy-revalidateCache-Control directive- Configurable Site-wide whether to respect must-revalidate directive, or only if from list of IPs, or some sort of authentication mechanism
- Configurable Per route
-
Add the
publicCache-Control directive unlessprivateis received from backend.- Configurable Site-wide
- Configurable Per route
-
Add
Expiresheader to responses if not in response from backend.- Configurable Cache TTL
- Configurable whether to overwrite backend Expires
- Configure whether to serve stale content while refreshing, or multiplex requests into a single request and serve new content to all of them
- Configurable Site-wide
- Configurable Per route
-
Add ability to configure which headers to include in the Request hash (e.g. Accept-Language)
- Configurable Site-wide
- Configurable Per route
-
If cache miss, but after refresh Validate matches, send 304 Response
-
Check
Varyheader from response and handle properly -
Handle
stale-while-revalidate- Configurable Site-wide (whether to respect it)
- Configurable Per route
-
After fetching a route with multiplexer, check vary headers, bucket queued requests based on the header, and do a fetch for each variant.