# signImgproxyPath _(no submodules)_ ## 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).