cache_handler

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Feb 15, 2022 License: Apache-2.0 Imports: 6 Imported by: 0

README

Cache Middleware Handler

This package provide a cache middleware handler function for Golang that can be set before http.HandlerFunc functions. The goal is to increase the performance and reduce load on third party e.g. databases by using a cache. The caching use the path and optionally the method, query parameter values and header values as a key for the cache. Currently the following stores are supported for caching:

  • in-memory
  • filesystem
  • Redis

I tried to keep the configuration as simple as possible. The following example shows a simple scenario for this package. A more detailed documentation is placed below.

// ...
import (
	"cache_handler/"
	"cache_handler/store"
)
// ...
func dbQueryHandler(w http.ResponseWriter, r *http.Request) { /* ... */ }
// ...
// Create a store for cached data
store := store.NewInMemoryStore(10 * time.Minute)
// Add the http handler and configuration to the cache middleware
dbQueryCacheMiddlewareHandler := cache_handler.NewMiddleware(
  dbQueryHandler, // http handler
  store, // store to use

  // Optionally add some bypass permissions to allow bypass when
  // - header contains specific field with value
  cache_handler.AllowBypassHeader{Key: "Cache-Status", Value: "bypass"},

  // Optionally define grouping for the cached data
  // e.g.
  // - each Authorization (user) has it's own cache
  cache_handler.UseHeaderKey{Key: "Authorization"},
  // - results are different depending query parameter
  cache_handler.UseQueryParamsKey{Key: "name"},
  cache_handler.UseQueryParamsKey{Key: "department"},
)

http.HandleFunc("/users", dbQueryCacheMiddlewareHandler)

documentation

storage

The storage is used to store cached data.

in memory

This storage type uses the RAM to store cached data.

// NewInMemoryStore(expiration time.Duration)
store := store.NewInMemoryStore(
  // define how long cached data are valid
  1 * time.Second,
)
filesystem

This storage type uses the filesystem to store cached data.

// NewFilesystem(basePath string, expiration time.Duration)
store := store.NewFilesystem(
  // path to the directory where cache files should stored
  "/tmp/cache",
  // define how long cached data are valid
  1*time.Second
)
Redis

This storage type uses the Redis to store cached data.

// NewRedisStore(endpoint string, port int, username string, password string, expiration time.Duration)
store := store.NewRedisStore(
  // URL to the redis service
  redisURL,
  // port to the redis service (set to 0 to use default)
  port,
  // username and password if required, if not set an empty string
  "username",
  "password",
  // define how long cached data are valid
  1*time.Second
)
middleware usage
// NewMiddleware(next http.HandlerFunc, store store.Store, opts ...Options)
cacheMiddlewareHandler := cache_handler.NewMiddleware(
	// next http handler func that needs to be cached
  httpHandler,
  // storage to use for cached data
  store,
  // List of options e.g.
  UseHeaderKey{Key: "Authorization"},
  UseQueryParamsKey{Key: "name"},
)
// use it as handler func
http.HandleFunc("/", cacheMiddlewareHandler)
options

Options are optional configuration parameter. There are two types of options:

  • options to define how to generate the key for caching
  • options to define when to bypass the cache

Lets assume an API endpoint /todo accept all kinds of HTTP methods and allow filter query parameter for get methods. So the cache should only do his job on get methods with corresponding filter. In addition, different users have different views of the list. The users can be differentiated by their Authorization header. It should be also possible to disable caching by setting Cache-Status to bypass or dev on the header. How to use this package on this case?

  1. key options

1.1. UseQueryParamsKey{Key string} can be used to set a query parameter as key for the caching. By setting filter as Key - filter=buy and filter=prepare will have their own cached data.

cache_handler.UseQueryParamsKey{Key: "filter"}

1.2. UseHeaderKey{Key string} can be used to set a header field as key for the caching. By setting Authorization as Key - each user (defined by the header field) has their own cached data.

cache_handler.UseHeaderKey{Key: "Authorization"}
  1. bypass options 2.1. TestAllowBypassMethod{Key string} can be user to define methods that should be bypassed. For our example post, put and delete. This is not case-sensitive.
cache_handler.TestAllowBypassMethod{Key: "post"}
cache_handler.TestAllowBypassMethod{Key: "PUT"}
cache_handler.TestAllowBypassMethod{Key: "dElEtE"}

2.2. AllowBypassHeader{Key string, Value string} can be used to define header fields that allows bypass. In our example we want to take a look at Cache-Status header field.

cache_handler.AllowBypassHeader{Key: "Cache-Status", Value: "bypass"}
cache_handler.AllowBypassHeader{Key: "Cache-Status", Value: "dev"}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewMiddleware

func NewMiddleware(next http.HandlerFunc, store store.Store, opts ...Options) http.HandlerFunc

Types

type AllowBypassHeader

type AllowBypassHeader struct{ Key, Value string }

AllowBypassHeader enable a client to set the `Cache-Status` header to `bypass` so he will not get cached data

func (AllowBypassHeader) ExtractBool

func (opt AllowBypassHeader) ExtractBool(r *http.Request) bool

ExtractBool check if request can bypass depending on request

func (AllowBypassHeader) ExtractString

func (opt AllowBypassHeader) ExtractString(r *http.Request) string

ExtractString does nothing but return empty string (function required to match the interface)

type AllowBypassMethod

type AllowBypassMethod struct{ Key string }

AllowBypassMethod defined methods that automatically bypass the caching e.g. post or put

func (AllowBypassMethod) ExtractBool

func (opt AllowBypassMethod) ExtractBool(r *http.Request) bool

ExtractBool check if request can bypass depending on request

func (AllowBypassMethod) ExtractString

func (opt AllowBypassMethod) ExtractString(r *http.Request) string

ExtractString does nothing but return empty string (function required to match the interface)

type HttpRecorder

type HttpRecorder struct {
	http.ResponseWriter
	Body *bytes.Buffer
}

HttpRecorder is a custom response writer that records the body

func NewHttpRecorder

func NewHttpRecorder(responseWriter http.ResponseWriter) *HttpRecorder

NewHttpRecorder create a new NewHttpRecorder with given ResponseWriter

func (*HttpRecorder) Write

func (hr *HttpRecorder) Write(buf []byte) (int, error)

Write byte data is written to rw.Body, if not nil.

func (*HttpRecorder) WriteString

func (hr *HttpRecorder) WriteString(str string) (int, error)

WriteString string data is written to rw.Body, if not nil.

type Options

type Options interface {
	ExtractString(r *http.Request) string
	ExtractBool(r *http.Request) bool
}

Options represent a option for the middleware

type UseHeaderKey

type UseHeaderKey struct{ Key string }

UseQueryParamsKey tells the cache to........

func (UseHeaderKey) ExtractBool

func (opt UseHeaderKey) ExtractBool(r *http.Request) bool

ExtractBool does nothing but return false (function required to match the interface)

func (UseHeaderKey) ExtractString

func (opt UseHeaderKey) ExtractString(r *http.Request) string

ExtractString key from request and return the string

type UseMethodKey

type UseMethodKey struct{}

UseMethodKey tells the cache to use the http method as part of the key

func (UseMethodKey) ExtractBool

func (opt UseMethodKey) ExtractBool(r *http.Request) bool

ExtractBool does nothing but return false (function required to match the interface)

func (UseMethodKey) ExtractString

func (opt UseMethodKey) ExtractString(r *http.Request) string

ExtractString key from request and return the string

type UsePathKey

type UsePathKey struct{}

UsePathKey tells the cache to use path as part of the key

func (UsePathKey) ExtractBool

func (opt UsePathKey) ExtractBool(r *http.Request) bool

ExtractBool does nothing but return false (function required to match the interface)

func (UsePathKey) ExtractString

func (opt UsePathKey) ExtractString(r *http.Request) string

ExtractString key from request and return the string

type UseQueryParamsKey

type UseQueryParamsKey struct{ Key string }

UseQueryParamsKey tells the cache to use query parameter value for given key as part of the key

func (UseQueryParamsKey) ExtractBool

func (opt UseQueryParamsKey) ExtractBool(r *http.Request) bool

ExtractBool does nothing but return false (function required to match the interface)

func (UseQueryParamsKey) ExtractString

func (opt UseQueryParamsKey) ExtractString(r *http.Request) string

ExtractString key from request and return the string

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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