httpcache

package module
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Mar 9, 2025 License: MIT Imports: 10 Imported by: 1

README

httpcache

Go Report Card Go Version Go Reference

httpcache is a local cache for HTTP requests and responses, wrapping http.RoundTripper from Go standard library.

Features

httpcache has a few useful features:

  • Store and retrieve HTTP responses for any type of request;
  • Expire responses after a customisable time duration;
  • Decide when to store responses based on status code and request method.

If you want to request a feature then please open a GitHub Issue today!

Quick Start

This module can be installed using the command line:

go get -u github.com/alexmerren/httpcache

Here's an example of using the httpcache module to cache responses:

func main() {
	// Create a new SQLite database to store HTTP responses.
	cache, _ := httpcache.NewSqliteCache("database.sqlite")

	// Create a config with a behaviour of:
	// 	- Storing responses with status code 200;
	// 	- Storing responses from HTTP requests using method "GET";
	// 	- Expiring responses after 7 days...
	config := httpcache.NewConfigBuilder().
		WithAllowedStatusCodes([]int{http.StatusOK}).
		WithAllowedMethods([]string{http.MethodGet}).
		WithExpiryTime(time.Duration(60*24*7) * time.Minute).
		Build()

	// ... or use the default config.
	config = httpcache.DefaultConfig

	// Create a transport with the SQLite cache and config.
	cachedTransport, _ := httpcache.NewTransport(config, cache)

	// Create a HTTP client with the cached roundtripper.
	httpClient := http.Client{
		Transport: cachedTransport,
	}

	// Do first request to populate local database.
	httpClient.Get("https://www.google.com")

	// Subsequent requests read from database with no outgoing HTTP request.
	for _ = range 10 {
		response, _ := httpClient.Get("https://www.google.com")
		defer response.Body.Close()
		responseBody, _ := io.ReadAll(response.Body)

		fmt.Println(string(responseBody))
	}
}

❓ Questions and Support

Any questions can be submitted via GitHub Issues. Feel free to start contributing or asking any questions required!

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrMissingCache will be returned if cache is not set when creating an
	// instance of [Transport].
	ErrMissingCache = errors.New("cache not set when creating transport")

	// ErrMissingConfig will be returned if config is not set when creating an
	// instance of [Transport].
	ErrMissingConfig = errors.New("config not set when creating transport")
)
View Source
var DefaultConfig = NewConfigBuilder().
	WithAllowedStatusCodes(defaultAllowedStatusCodes).
	WithAllowedMethods(defaultAllowedMethods).
	WithExpiryTime(defaultExpiryTime).
	Build()

DefaultConfig creates a Config with default values, namely:

View Source
var ErrNoDatabase = errors.New("no database connection")

ErrNoDatabase denotes when the database does not exist or has not been constructed correctly.

View Source
var (
	// ErrNoResponse describes when the cache does not have a response stored.
	// [Transport] will check if ErrNoResponse is returned from [Cache.Read]. If
	// ErrNoResponse is returned, then the request/response will be saved with [Save].
	ErrNoResponse = errors.New("no stored response")
)

Functions

func NewConfigBuilder

func NewConfigBuilder() *configBuilder

Types

type Cache

type Cache interface {

	// Save a response for a HTTP request using [context.Background].
	Save(response *http.Response, expiryTime *time.Duration) error

	// Read a saved response for a HTTP request using [context.Background].
	Read(request *http.Request) (*http.Response, error)

	// Save a response for a HTTP request with a [context.Context]. expiryTime
	// is the duration from [time.Now] to expire the response.
	SaveContext(ctx context.Context, response *http.Response, expiryTime *time.Duration) error

	// Read a saved response for a HTTP request with a [context.Context]. If no
	// response is saved for the corresponding request, or the expiryTime has
	// been surpassed, then return [ErrNoResponse].
	ReadContext(ctx context.Context, request *http.Request) (*http.Response, error)
}

Cache is the entrypoint for saving and reading responses. This can be implemented for a custom method to cache responses.

type Config

type Config struct {

	// AllowedStatusCodes describes if a HTTP response should be saved by
	// checking that it's status code is accepted by [Cache]. If the HTTP
	// response's status code is not in AllowedStatusCodes, then do not persist.
	//
	// This is a required field.
	AllowedStatusCodes []int

	// AllowedMethods describes if a HTTP response should be saved by checking
	// if the HTTP request's method is accepted by the [Cache]. If the HTTP
	// request's method is not in AllowedMethods, then do not persist.
	//
	// This is a required field.
	AllowedMethods []string

	// ExpiryTime describes when a HTTP response should be considered invalid.
	ExpiryTime *time.Duration
}

Config describes the configuration to use when saving and reading responses from Cache using the Transport.

type SqliteCache

type SqliteCache struct {
	Database *sql.DB
}

SqliteCache is a default implementation of Cache which creates a local SQLite cache to persist and to query HTTP responses.

func NewSqliteCache

func NewSqliteCache(databaseName string) (*SqliteCache, error)

NewSqliteCache creates a new SQLite database with a certain name. This name is the filename of the database. If the file does not exist, then we create it. If the file is in a non-existent directory, we create the directory.

func (*SqliteCache) Read

func (s *SqliteCache) Read(request *http.Request) (*http.Response, error)

func (*SqliteCache) ReadContext

func (s *SqliteCache) ReadContext(ctx context.Context, request *http.Request) (*http.Response, error)

func (*SqliteCache) Save

func (s *SqliteCache) Save(response *http.Response, expiryTime *time.Duration) error

func (*SqliteCache) SaveContext

func (s *SqliteCache) SaveContext(ctx context.Context, response *http.Response, expiryTime *time.Duration) error

type Transport

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

Transport is the main interface of the package. It uses Cache to persist HTTP response, and and uses configuration values from Config to interpret requests and responses.

func NewTransport

func NewTransport(config *Config, cache Cache) (*Transport, error)

NewTransport creates a Transport. If the cache is nil, return ErrMissingCache. If the config is nil, return ErrMissingConfig.

func (*Transport) RoundTrip

func (t *Transport) RoundTrip(request *http.Request) (*http.Response, error)

RoundTrip wraps the http.DefaultTransport RoundTrip to execute HTTP requests and persists, if necessary, the responses. If Cache returns ErrNoResponse, then execute a HTTP request and persist the response if passing the criteria in [Transport.shouldSaveResponse].

Jump to

Keyboard shortcuts

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