githubhttp

package
v0.0.0-...-319015a Latest Latest
Warning

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

Go to latest
Published: Apr 20, 2026 License: MIT, Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

Package githubhttp builds the layered HTTP transport chain used for all GitHub REST API calls: auth → httpcache (ETag + two-tier LRU/disk store) → revalidation suppressor.

The goal is to make repeated per-repo Contents API probes (e.g. by eza --icons listing ~/github.com/<owner>/) effectively free: once warm, each request is served from the in-process LRU without any network I/O, for SuppressDuration after the last hit.

Chain shape (outermost first):

Suppressor               ← 5-min window: Cache-Control: only-if-cached, zero network
 └─ httpcache.Transport  ← RFC-7234 ETag cache, X-From-Cache: 1 on hit
     └─ AuthTransport    ← token injection + header normalisation
         └─ http.DefaultTransport

Index

Constants

View Source
const (
	DefaultMemCacheMB    = 128
	DefaultSuppressDur   = 5 * time.Minute
	DefaultMaxCachedURLs = 1000
)

Default cache sizing + suppression window.

Variables

This section is empty.

Functions

This section is empty.

Types

type AuthTransport

type AuthTransport struct {
	Token  string
	Base   http.RoundTripper
	Logger *slog.Logger
}

AuthTransport attaches an auth token + normalises response headers so the downstream httpcache layer can actually cache things.

Normalisations (all required by gregjones/httpcache):

  • Date header set/refreshed on 304s and any response missing it.
  • Vary and X-Varied-* stripped (GitHub returns Vary: Accept, Accept-Encoding which would otherwise partition the cache and defeat it for nearly every request).
  • Synthetic ETag injected on 404s so "this doesn't exist" is cacheable (avoids re-probing missing paths).

func (*AuthTransport) RoundTrip

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

RoundTrip implements http.RoundTripper.

type Client

type Client struct {
	HTTP *http.Client

	// Suppressor is nil when Disabled. Its ClearSuppressionCache
	// method makes the next request for any URL fall through to the
	// httpcache revalidation path instead of the "only-if-cached"
	// shortcut.
	Suppressor *Suppressor
}

Client is the assembled HTTP client plus the runtime handle the SIGUSR1 handler needs to force-refresh cached data.

func New

func New(cfg Config) (*Client, error)

New assembles the chain described in the package doc.

type Config

type Config struct {
	// Token is the GitHub PAT to attach as `Authorization: token <T>`.
	// Empty => anonymous.
	Token string

	// CacheDir is the disk-cache root (e.g. ~/.cache/ghfs). Empty
	// disables the disk tier (in-memory LRU only). Disabled wins
	// over both.
	CacheDir string

	// MemCacheMB is the in-memory LRU budget in MiB. 0 => default.
	MemCacheMB int

	// SuppressDuration is how long a URL stays "just served from
	// cache, don't even revalidate". 0 => default.
	SuppressDuration time.Duration

	// Disabled skips the entire cache chain (just AuthTransport).
	Disabled bool

	// Logger receives HTTP request traces (at debug) and cache
	// clear notifications (at info). Must be non-nil.
	Logger *slog.Logger
}

Config configures New.

type Suppressor

type Suppressor struct {
	Base             http.RoundTripper
	SuppressDuration time.Duration
	Logger           *slog.Logger
	MaxEntries       int // 0 => DefaultMaxCachedURLs
	// contains filtered or unexported fields
}

Suppressor sits above httpcache. For SuppressDuration after a cache hit on a URL, it replays the request with Cache-Control: only-if-cached — httpcache then serves from storage without ever touching the network (not even an If-None-Match revalidation).

Without this, GitHub will 304 every request with ~30ms RTT, which multiplied by N repos becomes visible to eza --icons.

func (*Suppressor) ClearSuppressionCache

func (r *Suppressor) ClearSuppressionCache()

ClearSuppressionCache forces the next request for every URL to go through revalidation (304 or full response) rather than the only-if-cached shortcut. SIGUSR1 should call this so users can see fresh data without unmounting.

func (*Suppressor) RoundTrip

func (r *Suppressor) RoundTrip(req *http.Request) (*http.Response, error)

RoundTrip implements http.RoundTripper.

Jump to

Keyboard shortcuts

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