first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,95 @@
# signImgproxyPath
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
`signImgproxyPath` computes the HMAC-SHA256 URL signature that
imgproxy requires when it is configured with a key + salt. It is the
single source of truth for how the TypeScript port and the upstream
Go module agree on bytes: any URL signed here verifies against the Go
implementation and vice-versa.
The function decodes the hex-encoded `key` and `salt` into raw bytes,
concatenates the salt with the UTF-8 encoded `path`, runs HMAC-SHA256
under the key, and base64url-encodes the digest without padding. Bad
hex on either input raises a typed `CaddyImgproxyError`
(`INVALID_KEY` / `INVALID_SALT`) so misconfiguration surfaces
immediately rather than at the imgproxy boundary.
## Features
- Verbatim byte-level port of the Go `signPath` function.
- Pluggable hash via the optional `hash` parameter — supply a native
/ HSM / WebCrypto-backed implementation when needed.
- Hex validation stricter than `@suaveplan/crypto-hash`'s `fromHex`
(lower-case only) to keep wire-format round-trips deterministic.
- Throws typed `CaddyImgproxyError` on every failure path.
## Usage: Basic
```ts
import { signImgproxyPath } from "@suaveplan/caddy-imgproxy";
const signature = signImgproxyPath({
key: "aa11bbcc",
salt: "deadbeef",
path: "/g:ce/rs:fill:800:450/plain/s3://images/example.com/avatar@png",
});
signature; // "E3ytdnTM6THWihFdTWqY4YGQIV-6K969S-8jb4AaE4U"
```
## Usage: Advanced
```ts
import { signImgproxyPath, type SignerHashLike } from "@suaveplan/caddy-imgproxy";
// Plug a WebCrypto-backed signer in a Cloudflare Worker:
const wcHash: SignerHashLike = {
hmac(_algo, key, data) {
// ... call into crypto.subtle.sign synchronously via a vendored
// implementation, return the digest as Uint8Array.
return data;
},
};
const sig = signImgproxyPath({
key: "deadbeef",
salt: "feedface",
path: "/plain/s3://images/example.com/photo@webp",
hash: wcHash,
});
```
## API Reference
### `signImgproxyPath(options: SignImgproxyPathOptions): string`
- **Parameters:**
- `options.key` — lower-hex HMAC key, even length, non-empty.
- `options.salt` — lower-hex salt, even length, non-empty.
- `options.path` — the imgproxy path being signed.
- `options.hash` — optional `SignerHashLike` injection seam.
- **Returns:** base64url-encoded signature, no padding.
- **Throws:**
- `CaddyImgproxyError(INVALID_KEY)` for malformed / empty / odd-length key.
- `CaddyImgproxyError(INVALID_SALT)` for malformed / empty / odd-length salt.
### `SignerHashLike`
Structural type with a single `hmac(algorithm, key, data)` method
returning a `Uint8Array`. Lets callers swap the default Noble-backed
implementation for a native, HSM, or WebCrypto-backed alternative.
## Implementation Notes
The function pre-allocates the `salt || path` buffer in one
`Uint8Array(saltBytes.length + pathBytes.length)` allocation so the
hot path never reallocates. UTF-8 encoding goes through
`TextEncoder`, which is available in every modern JS runtime
(Node ≥ 14, all browsers, Cloudflare Workers, Deno, Bun). The Go
reference uses `[]byte(path)` which is identical for ASCII paths and
spec-compliant for arbitrary UTF-8 (the imgproxy upstream uses the
same convention).