AWS Request Signing
On AWS, Gothic serves your app from a Lambda Function URL behind CloudFront, locked down with Origin Access Control (OAC). OAC only accepts requests that carry a valid SigV4 signature, and that signature includes a SHA-256 of the request body in the x-amz-content-sha256 header. Omit it or send the wrong value and the origin replies 403.
The body only exists in the browser, so the hash has to be computed there, as each request goes out. Without it, every POST, PUT, PATCH and DELETE would fail the moment it went behind the CDN.
How Gothic handles it
Signing switches on only when GOTHIC_PROVIDER=AWS — the flag the deploy sets for you — and covers both ways your app talks to its backend: htmx requests and Fetch calls from a WASM component.
htmx requests
The Gothic core WASM hooks htmx:configRequest and fills in x-amz-content-sha256 by method:
# GET, DELETE — no body → the fixed empty-body hash
x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
# POST, PUT, PATCH — SHA256 of the urlencoded form body
x-amz-content-sha256: <sha256 of the body>
# multipart uploads — streamed, so signed as an unsigned payload
x-amz-content-sha256: UNSIGNED-PAYLOADA request that fires during boot (an hx-trigger="load") is held until the signer is ready, so nothing ever goes out unsigned.
Fetch from a WASM component
Fetch, FetchAsync and FetchChan call the browser directly rather than going through htmx, so they carry their own signature. The hash covers the exact bytes you pass — Body or BodyBytes — which is how a JSON payload from Encode gets signed correctly. A request with no body sends the empty-body hash, same as a GET.
Only same-origin requests are signed: the ones that travel through your own CloudFront distribution and face the check. A call to a third-party API never carries the header — that value means nothing to them, and your request shape is not theirs to see. Relative URLs like /api/orders are always same-origin; an absolute URL is signed only when its origin matches the page exactly.
Everywhere else
Off AWS — Docker, a VPS, GCP, Azure, or local — the signer stays off. Nothing to enable, nothing to configure.
Signing lives in the WASM core, so there is no amz-content-sha256 htmx extension to add — no hx-ext and no custom JavaScript configuration.
That covers the AWS building blocks. Ready to ship? Let's install the dependencies and deploy your app.
