PushStack Docs
git-fs-s3

Git smart-HTTP overview

Why the /http module exists, its shape, and the HttpHooks instrumentation seam.

git-fs-s3/http implements the git smart-HTTP protocol (info/refs, upload-pack, receive-pack) as plain functions over a Repo — no framework assumptions, Fetch-API-shaped inputs and outputs. Extracted from the same production git-hosting service's HTTP layer, so it's what actually serves git clone/git push over HTTPS today: pkt-line framing, side-band-64k packfile chunking, compare-and-swap ref updates, and pack consolidation.

Node.jsCloudflare WorkersDenoBrowser

This module is pure Web APIs (Uint8Array, Web Crypto, CompressionStream) — no node:crypto, no node:zlib, no Buffer. It runs anywhere git-fs-s3 itself does.

The three request types

info/refs

GET .../info/refs?service=git-upload-pack (or git-receive-pack) — the ref advertisement a client fetches before deciding what to want or push. Handled by handleInfoRefs.

upload-pack

POST .../git-upload-pack — serves a clone or fetch. Handled by handleUploadPack.

receive-pack

POST .../git-receive-pack — accepts a push. Handled by parseReceivePackBody + applyReceivePack.

See Serving clones and pushes for a full worked example wiring all three into a route handler.

HttpHooks

Every handler in this module accepts an optional hooks argument — the same instrumentation seam used throughout /ops:

interface HttpHooks {
  /** Wrap a timed sub-step. Default: run directly. */
  step?<T>(label: string, fn: () => Promise<T>): Promise<T>;
  /** Non-fatal problem sink (missing objects, failed repacks). */
  onWarn?(message: string, error?: unknown): void;
}

step is shaped exactly like a typical app-level timing wrapper (e.g. perfStep(label, fn)) — drop yours in directly:

const hooks = { step: perfStep, onWarn: (m, e) => logWarn('git-http', m, e) };
await handleInfoRefs(repo, { service: 'git-upload-pack' }, hooks);

Ref validation is not optional

Every client-supplied ref name in a push is validated with isSafeFullRefName inside applyReceivePack before it reaches any filesystem call — git.commit/git.merge/git.deleteBranch and the raw git.resolveRef/git.deleteRef/git.writeRef isomorphic-git calls this module uses internally do not validate ref names themselves. This is handled for you inside applyReceivePack. If you build additional git-touching endpoints on top of this package outside of /http, run any ref/branch name from request input through isSafeFullRefName / isSafeBranchName / isSafeRefName / isSafeRepoPath (exported from the root package) yourself first — an unvalidated "../"-laden name is a cross-repo path traversal on any shared-storage server.

On this page