cache

package module
v0.3.4 Latest Latest
Warning

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

Go to latest
Published: Jul 9, 2019 License: MPL-2.0 Imports: 14 Imported by: 1

README

caddy cache

Build Status

This is a simple caching plugin for caddy server

Notice: Although this plugin works with static content it is not advised. Static content will not see great benefits. It should be used when there are slow responses, for example when using caddy as a proxy to a slow backend.

Build

Notice: Build requires Go 1.12 or higher.

To use it you need to compile your own version of caddy with this plugin. First fetch the code

  • export GO111MODULE=on
  • go get -u github.com/caddyserver/caddy/...
  • go get -u github.com/nicolasazrak/caddy-cache/...

Then update the file in $GOPATH/src/github.com/caddyserver/caddy/caddy/caddymain/run.go and import _ "github.com/nicolasazrak/caddy-cache".

And finally build caddy with:

  • cd $GOPATH/src/github.com/caddyserver/caddy/caddy
  • ./build.bash

This will produce the caddy binary in that same folder. For more information about how plugins work read this doc.

Usage

Example minimal usage in Caddyfile

caddy.test {
    proxy / yourserver:5000
    cache
}

This will store in cache responses that specifically have a Cache-control, Expires or Last-Modified header set.

For more advanced usages you can use the following parameters:

  • match_path: Paths to cache. For example match_path /assets will cache all successful responses for requests that start with /assets and are not marked as private.
  • match_header: Matches responses that have the selected headers. For example match_header Content-Type image/png image/jpg will cache all successful responses that with content type image/png OR image/jpg. Note that if more than one is specified, anyone that matches will make the response cacheable.
  • path: Path where to store the cached responses. By default it will use the operating system temp folder.
  • default_max_age: Max-age to use for matched responses that do not have an explicit expiration. (Default: 5 minutes)
  • status_header: Sets a header to add to the response indicating the status. It will respond with: skip, miss or hit. (Default: X-Cache-Status)
  • cache_key: Configures the cache key using Placeholders, it supports any of the request placeholders. (Default: {method} {host}{path}?{query})
caddy.test {
    proxy / yourserver:5000
    cache {
        match_path /assets
        match_header Content-Type image/jpg image/png
        status_header X-Cache-Status
        default_max_age 15m
        path /tmp/caddy-cache
    }
}
Logs

Caddy-cache adds a {cache_status} placeholder that can be used in logs.

Benchmarks

Benchmark files are in benchmark folder. Tests were run on my Lenovo G480 with Intel i3 3220 and 8gb of ram.

  • First test: Download sherlock.txt (608 Kb) file from the root (caddy.test3), a proxy to root server (caddy.test2) and a proxy to root server with cache (caddy.test).

    wrk -c 400 -d 30s --latency -t 4 http://caddy.test:2015/sherlock.txt

    Req/s Throughput 99th Latency
    proxy + cache 4548.03 2.64 GB/s 561.39 ms
    proxy 1043.61 619.65 MB/s 1.00 s
    root 3668.14 2.13 GB/s 612.39 ms
  • Second test: Download montecristo.txt (2,6 Mb) file from the root (caddy.test3), a proxy to root server (caddy.test2) and a proxy to root server with cache (caddy.test).

    wrk -c 400 -d 30s --latency -t 4 http://caddy.test:2015/montecristo.txt

    Req/s Throughput 99th Latency
    proxy + cache 1199.81 3.01 GB/s 1.65 s
    proxy 473.14 1.20 GB/s 1.81 s
    root 1064.44 2.66 GB/s 1.71 s
  • Third test: Download pg31674.txt (41 Kb) a root server (caddy.test5) with gzip and a proxy to root server with cache (caddy.test4).

    wrk -c 50 -d 30s --latency -H 'Accept-Encoding: gzip' -t 4 http://caddy.test4:2015/pg31674.txt

    Req/s Throughput 99th Latency
    proxy + cache 16547.84 242.05 MB/s 22.48ms
    root 792.08 11.60 MB/s 109.98ms

Todo list

  • Support vary header
  • Add header with cache status
  • Stream responses while fetching them from upstream
  • Locking concurrent requests to the same path
  • File disk storage for larger objects
  • Add a configuration to not use query params in cache key (via cache_key directive)
  • Purge cache entries #1
  • Serve stale content if proxy is down
  • Punch hole cache
  • Do conditional requests to revalidate data
  • Max entries size

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Setup

func Setup(c *caddy.Controller) error

Setup creates a new cache middleware

Types

type CacheRule

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

CacheRule determines if a request should be cached

type Config

type Config struct {
	StatusHeader     string
	DefaultMaxAge    time.Duration
	LockTimeout      time.Duration
	CacheRules       []CacheRule
	Path             string
	CacheKeyTemplate string
}

type HTTPCache

type HTTPCache struct {
	// contains filtered or unexported fields
}

func NewHTTPCache

func NewHTTPCache(cacheKeyTemplate string) *HTTPCache

func (*HTTPCache) Get

func (cache *HTTPCache) Get(request *http.Request) (*HTTPCacheEntry, bool)

func (*HTTPCache) Put

func (cache *HTTPCache) Put(request *http.Request, entry *HTTPCacheEntry)

type HTTPCacheEntry

type HTTPCacheEntry struct {
	Request  *http.Request
	Response *Response
	// contains filtered or unexported fields
}

HTTPCacheEntry saves the request response of an http request

func NewHTTPCacheEntry

func NewHTTPCacheEntry(key string, request *http.Request, response *Response, config *Config) *HTTPCacheEntry

NewHTTPCacheEntry creates a new HTTPCacheEntry for the given request and response and it also calculates if the response is public

func (*HTTPCacheEntry) Clean

func (e *HTTPCacheEntry) Clean() error

Clean removes the response if it has an associated file

func (*HTTPCacheEntry) Fresh

func (e *HTTPCacheEntry) Fresh() bool

Fresh returns if the entry is still fresh

func (*HTTPCacheEntry) Key

func (e *HTTPCacheEntry) Key() string

func (*HTTPCacheEntry) WriteBodyTo

func (e *HTTPCacheEntry) WriteBodyTo(w http.ResponseWriter) error

WriteBodyTo sends the body to the http.ResponseWritter

type Handler

type Handler struct {
	// Handler configuration
	Config *Config

	// Cache is where entries are stored
	Cache *HTTPCache

	// Next handler
	Next httpserver.Handler

	// Handles locking for different URLs
	URLLocks *URLLock
}

Handler is the main cache middleware

func NewHandler

func NewHandler(Next httpserver.Handler, config *Config) *Handler

NewHandler creates a new Handler using Next middleware

func (*Handler) ServeHTTP

func (handler *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error)

type HeaderCacheRule

type HeaderCacheRule struct {
	Header string
	Value  []string
}

HeaderCacheRule matches if given Header matches any of the values

type PathCacheRule

type PathCacheRule struct {
	Path string
}

PathCacheRule matches if the request starts with given Path

type Response

type Response struct {
	Code      int         // the HTTP response code from WriteHeader
	HeaderMap http.Header // the HTTP response headers
	// contains filtered or unexported fields
}

func NewResponse

func NewResponse() *Response

NewResponse returns an initialized Response.

func (*Response) Clean

func (rw *Response) Clean() error

Clean the body if it is set

func (*Response) Close

func (rw *Response) Close() error

Close means there won't be any more Writes It closes body if it was set before It should be called after SetBody using WaitBody() Otherwise body won't be closed blocking the response

func (*Response) CloseNotify

func (rw *Response) CloseNotify() <-chan bool

TODO check this

func (*Response) Flush

func (rw *Response) Flush()

func (*Response) Header

func (rw *Response) Header() http.Header

Header returns the response headers.

func (*Response) SetBody

func (rw *Response) SetBody(body storage.ResponseStorage)

func (*Response) WaitBody

func (rw *Response) WaitBody()

WaitBody blocks until body is Set

func (*Response) WaitClose

func (rw *Response) WaitClose()

WaitClose blocks until Close is called

func (*Response) WaitHeaders

func (rw *Response) WaitHeaders()

WaitHeaders blocks until headers are sent

func (*Response) Write

func (rw *Response) Write(buf []byte) (int, error)

Write is the io.Writer interface with the modification required To wait the body. This will wait until SetBody is called with The desired storage.

func (*Response) WriteHeader

func (rw *Response) WriteHeader(code int)

type URLLock

type URLLock struct {
	// contains filtered or unexported fields
}

func NewURLLock

func NewURLLock() *URLLock

func (*URLLock) Adquire

func (allLocks *URLLock) Adquire(key string) *sync.Mutex

Adquire a lock for given key

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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