awssign

package
v1.5.0-beta.1 Latest Latest
Warning

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

Go to latest
Published: Jul 20, 2026 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

Package awssign holds the PURE, host-testable body-hashing logic for the Gothic full-Go static core's AWS request signer (CloudFront OAC / SigV4). It has NO syscall/js dependency, so it compiles and runs under the standard host toolchain and can be unit-tested without a WASM runtime. The core's main package (wasm/core-runtime, //go:build js && wasm) is a thin js.Value adapter that lifts the htmx configRequest parameter set into [][2]string and calls into here to compute the x-amz-content-sha256 header value.

Why this exists

Gothic apps on AWS run behind CloudFront OAC (SigV4) → Lambda Function URL with authorization_type = AWS_IAM. Every htmx request that carries a body must send header x-amz-content-sha256 = sha256-hex(request body) or CloudFront's SigV4 body check rejects the request with HTTP 403. This package reproduces — byte-for-byte — the application/x-www-form-urlencoded body htmx 2.0.3 builds, so the hash we sign matches the bytes htmx actually sends.

Byte-exactness is the whole game

htmx serializes the body with its urlEncode helper: for each FormData entry (in insertion order) it emits encodeURIComponent(key) + "=" + encodeURIComponent(value), joined by "&". encodeURIComponent here means the JAVASCRIPT function, NOT Go's net/url — url.QueryEscape encodes space as "+" and escapes ! * ' ( ), both of which would change the bytes → wrong SHA-256 → HTTP 403. EncodeBody + encodeURIComponent below match JS encodeURIComponent exactly (space → %20, unreserved set A-Z a-z 0-9 - _ . ! ~ * ' ( ) passes through literally, every other UTF-8 byte → %XX uppercase).

Index

Constants

View Source
const EmptyBodyHash = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"

EmptyBodyHash is sha256("") in lowercase hex — the value to send when the request has no body (a GET/DELETE with its params in the URL, or a POST with no parameters). Hardcoded so the common empty-body path never hashes.

Variables

This section is empty.

Functions

func ContentHashHex

func ContentHashHex(entries [][2]string) string

ContentHashHex returns the x-amz-content-sha256 header value for a urlencoded body built from entries: sha256 of EncodeBody(entries) as lowercase hex. When entries is empty the body is empty, so it returns the precomputed EmptyBodyHash without hashing. crypto/sha256 is synchronous, so the WASM adapter can call this inline in the htmx:configRequest listener.

func EncodeBody

func EncodeBody(entries [][2]string) string

EncodeBody builds the application/x-www-form-urlencoded body EXACTLY as htmx 2.0.3 does: for each [key, value] pair in the given order, encodeURIComponent(key) + "=" + encodeURIComponent(value), joined by "&". The pair order MUST match htmx's FormData insertion order (the caller iterates e.detail.parameters via forEach to preserve it). Split out from the hash so tests can assert the exact body bytes independently of the digest.

Types

This section is empty.

Jump to

Keyboard shortcuts

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