etagcache

package
v0.18.0 Latest Latest
Warning

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

Go to latest
Published: Oct 7, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package etagcache provides an HTTP transport that makes conditional requests against the GitHub API.

GitHub returns an ETag with most GET responses and answers a repeat request carrying If-None-Match with 304 Not Modified when nothing changed. A 304 does not count against the rate limit. Transport remembers the ETag and body of each successful GET, sends the conditional headers on the next request for the same URL, and when GitHub answers 304, returns the cached response as if it were a fresh 200, so callers such as go-github never see the 304.

Use it as the base transport of an authenticated client:

cache := etagcache.NewTransport(nil)
client, err := clientv1.NewClientWithOptions(ctx, clientv1.ClientOptions{
    Token:     token,
    Transport: cache,
})
// ... make requests, then:
fmt.Println(cache.Stats())

Entries are keyed by URL and by a hash of the Authorization header, so a store shared by clients with different tokens never serves one token's response to another. Cached bodies may contain private data; FileStore writes them with owner-only permissions.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Key

func Key(req *http.Request) string

Key returns the cache key for a request: the method and URL, plus a hash of the Authorization header so that responses are never shared between credentials.

Types

type Entry

type Entry struct {
	ETag         string      `json:"etag"`
	LastModified string      `json:"lastModified,omitempty"`
	Header       http.Header `json:"header"`
	Body         []byte      `json:"body"`
}

Entry is a cached response.

type FileStore

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

FileStore keeps one JSON file per entry in a directory, so a cache survives between runs of a command-line tool. Files are written with owner-only permissions and replaced atomically. Entries are never evicted; remove the directory to clear the cache.

func NewFileStore

func NewFileStore(dir string) (*FileStore, error)

NewFileStore returns a FileStore in dir, creating it if needed.

func (*FileStore) Dir

func (s *FileStore) Dir() string

Dir returns the cache directory.

func (*FileStore) Get

func (s *FileStore) Get(key string) (*Entry, error)

Get implements Store.

func (*FileStore) Set

func (s *FileStore) Set(key string, entry *Entry) error

Set implements Store.

type MemoryStore

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

MemoryStore keeps entries in memory, evicting the least recently used when MaxEntries is exceeded. It is safe for concurrent use.

func NewMemoryStore

func NewMemoryStore(maxEntries int) *MemoryStore

NewMemoryStore returns a MemoryStore holding at most maxEntries entries; zero or negative means unlimited.

func (*MemoryStore) Get

func (s *MemoryStore) Get(key string) (*Entry, error)

Get implements Store.

func (*MemoryStore) Len

func (s *MemoryStore) Len() int

Len returns the number of entries.

func (*MemoryStore) Set

func (s *MemoryStore) Set(key string, entry *Entry) error

Set implements Store.

type Stats

type Stats struct {
	// Requests is the number of requests passed through the transport.
	Requests int64
	// Hits is the number of requests GitHub answered with 304 Not Modified;
	// these did not count against the rate limit.
	Hits int64
	// Misses is the number of cacheable requests that were sent without a
	// cached entry, or whose entry was stale.
	Misses int64
	// Uncacheable is the number of requests that bypassed the cache: methods
	// other than GET and HEAD, or responses without an ETag.
	Uncacheable int64
}

Stats counts what the transport did.

func (Stats) String

func (s Stats) String() string

type Store

type Store interface {
	// Get returns the entry for key, or nil when there is none.
	Get(key string) (*Entry, error)
	// Set stores the entry for key, replacing any existing one.
	Set(key string, entry *Entry) error
}

Store persists entries. Implementations must be safe for concurrent use.

type Transport

type Transport struct {
	// Next performs the requests. nil means http.DefaultTransport.
	Next http.RoundTripper
	// Store holds cached responses.
	Store Store
	// OnStoreError is called when the store fails to read or write; the
	// request still proceeds without the cache. nil ignores store errors.
	OnStoreError func(err error)
	// contains filtered or unexported fields
}

Transport makes conditional requests using a Store. The zero value is not usable; use NewTransport.

func NewTransport

func NewTransport(next http.RoundTripper) *Transport

NewTransport returns a Transport over next (nil means http.DefaultTransport) backed by a new MemoryStore.

func NewTransportWithStore

func NewTransportWithStore(next http.RoundTripper, store Store) *Transport

NewTransportWithStore returns a Transport over next (nil means http.DefaultTransport) backed by store.

func (*Transport) RoundTrip

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

RoundTrip implements http.RoundTripper.

func (*Transport) Stats

func (t *Transport) Stats() Stats

Stats returns the counts so far.

Jump to

Keyboard shortcuts

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