aws/internal/codec/rest
Shared runtime helpers for the rest-protocol emitters
(restJson1, restXml). Holds the URI / query / header glue that
generated build_*_request functions call into for each
@httpLabel, @httpQuery, @httpHeader member.
Types
Checksum algorithm picked by the aws.protocols#httpChecksum
trait. Each variant maps to one of the AWS x-amz-checksum-*
request headers; the codegen / runtime middleware writes the
base64-encoded digest of the request body into that header
before signing.
pub type ChecksumAlgorithm {
ChecksumSha256
ChecksumSha1
ChecksumCrc32
ChecksumCrc32C
}
Constructors
-
ChecksumSha256 -
ChecksumSha1 -
ChecksumCrc32 -
ChecksumCrc32C
Values
pub fn add_prefix_headers(
headers: dict.Dict(String, String),
prefix: String,
entries: dict.Dict(String, String),
) -> dict.Dict(String, String)
Iterate @httpPrefixHeaders map members: for each entry,
emit a header <prefix><key>: <value>.
pub fn add_query(
existing: String,
name: String,
value: String,
) -> String
Append a query parameter pair. Returns the resulting query string
(without the leading ?); call sites prepend it themselves.
pub fn add_query_params(
query: String,
entries: dict.Dict(String, String),
) -> String
Iterate @httpQueryParams map members (Map<String, String>).
pub fn add_query_params_list(
query: String,
entries: dict.Dict(String, List(String)),
) -> String
Iterate @httpQueryParams map members (Map<String, List
pub fn append_content_encoding(
headers: dict.Dict(String, String),
encoding: String,
) -> dict.Dict(String, String)
Append a @requestCompression encoding to the Content-Encoding
header. Existing encodings (e.g. caller-set Content-Encoding: custom) are preserved with the new value appended after a comma:
custom + gzip ⇒ custom, gzip.
pub fn bool_header(
headers: dict.Dict(String, String),
name: String,
) -> option.Option(Bool)
pub fn build_path(uri_path: String, query: String) -> String
Build the full path: substitute labels, then append query (with ?)
if non-empty.
Merge a path that may already carry a static query string (from the
@http URI template, e.g. /Foo?bar=baz) with the dynamically
built query string from @httpQuery members. Either or both can be
empty. The static-query side wins on key order; dynamic params are
appended.
pub fn checksum_algorithm_from_wire(
wire: String,
) -> ChecksumAlgorithm
Translate a Smithy ChecksumAlgorithm enum’s wire value
(e.g. "SHA256", "CRC32C") to the runtime ChecksumAlgorithm
variant, falling back to ChecksumSha256 when the wire value
doesn’t match a supported algorithm. Used by the codegen’s
algorithm-member dispatch for aws.protocols#httpChecksum so
generated request builders can read the caller’s typed enum
choice without needing a per-service jump table.
pub fn checksum_header(
algorithm: ChecksumAlgorithm,
body: BitArray,
) -> #(String, String)
(header_name, base64_digest) pair for a body checksum. The
header name follows the AWS convention x-amz-checksum-<algo>
(lowercase). The digest is base64 of the raw bytes — same
padding rules as Content-MD5. Pure function; the
aws.protocols#httpChecksum middleware in the codegen layer
calls this and inserts the result into the request headers.
pub fn enum_header(
headers: dict.Dict(String, String),
name: String,
from_wire: fn(String) -> Result(t, String),
) -> option.Option(t)
Enum header — looks up a string header, then runs the supplied
<enum>_from_wire decoder. Falls through to None if the
header is missing or the wire value doesn’t match a known
variant (forgiving contract — unknown variants don’t crash
the response parse). The codegen passes the generated
<enum>_from_wire function directly so this stays
enum-agnostic.
pub fn enum_wire_value(j: json.Json) -> String
Extract the raw wire string from a JSON-encoded enum value. The
generated encode_<enum>_enum(v) returns a json.Json like
json.string("VALUE"); URI / query / header position wants just
VALUE. We render to JSON text and strip the surrounding quotes.
pub fn epoch_seconds_header(
headers: dict.Dict(String, String),
name: String,
) -> option.Option(json_timestamp.Timestamp)
Epoch-seconds timestamp header
(@timestampFormat("epoch-seconds"), integer seconds since 1970
in the header value).
pub fn float_header(
headers: dict.Dict(String, String),
name: String,
) -> option.Option(Float)
Float header — used for shapes that bind a Float member to a
response header. Falls through to None if the value can’t be
parsed; same forgiving contract as int_header / bool_header.
pub fn float_to_query(f: Float) -> String
Float → query / header / URI-label value. Uses Erlang’s short
formatter so 1.1 round-trips as the literal "1.1" — the AWS
SimpleScalarProperties protocol-test corpus rejects scientific
notation in these positions.
pub fn glacier_tree_hash(body: BitArray) -> BitArray
Compute the Glacier tree hash of body as raw bytes (caller
hex-encodes for the wire). Empty body degenerates to
SHA-256("") so the function is total. Matches
glacier_interceptors::compute_hash_tree in the Rust SDK.
pub fn http_date_header(
headers: dict.Dict(String, String),
name: String,
) -> option.Option(json_timestamp.Timestamp)
HTTP-date header — RFC 7231 §7.1.1.1 form
(Tue, 29 Apr 2014 18:30:38 GMT). The default @timestampFormat
for header bindings per Smithy core — covers Last-Modified,
Expires, Date, etc. Forgiving contract: missing header or
unparseable string → None.
pub fn idempotency_token() -> String
Generated @idempotencyToken value, used when a request member
with that trait is left as Option.None. Backed by the runtime
FFI so tests can pin a deterministic UUID via application:set_env.
pub fn int_header(
headers: dict.Dict(String, String),
name: String,
) -> option.Option(Int)
pub fn iso8601_header(
headers: dict.Dict(String, String),
name: String,
) -> option.Option(json_timestamp.Timestamp)
ISO 8601 timestamp header (@timestampFormat("date-time"),
2024-01-02T03:04:05Z).
pub fn maybe_set_header(
headers: dict.Dict(String, String),
name: String,
value: String,
) -> dict.Dict(String, String)
Set a header on the headers dict if the value is non-empty (Smithy
@httpHeader typically omits the header when the value is None).
pub fn maybe_set_list_header(
headers: dict.Dict(String, String),
name: String,
values: List(String),
) -> dict.Dict(String, String)
@httpHeader on a list member emits the values comma-joined, per
HTTP/1.1 header-folding rules. Some(["a", "b"]) becomes
Name: a, b. Empty lists drop the header entirely.
pub fn quote_list_string_entry(v: String) -> String
RFC 7230 list-header quoting for string elements. Smithy applies
this only to string-typed entries — timestamp values use the raw
Mon, 16 Dec ... GMT form even though it contains a comma.
pub fn set_default_header(
headers: dict.Dict(String, String),
name: String,
value: String,
) -> dict.Dict(String, String)
Insert a service-level default header only when the caller hasn’t
already provided one with the same name. Mirrors set_default_header
in the Rust SDK and the contains_key guard inside Glacier’s
add_checksum_treehash so caller @httpHeader-bound values win on
collision.
pub fn string_header(
headers: dict.Dict(String, String),
name: String,
) -> option.Option(String)
pub fn substitute_label(
template: String,
name: String,
value: String,
greedy: Bool,
) -> String
Substitute a single @httpLabel member into the URI template.
Templates use {Name} or {Name+} (the + marks a greedy label
that may contain /). Values are percent-encoded; greedy labels
preserve / in the value.
pub fn timestamp_to_header(epoch_seconds: Int) -> String
Format a timestamp for use in URI labels / query strings / headers.
Smithy’s default @timestampFormat for date-time (the
restJson1 + restXml default) is RFC 3339, e.g. 2019-12-16T23:48:18Z.
We always emit Z-suffixed UTC; the wire form remains stable even if
the input came from a system clock in a different zone.
pub fn with_checksum_header(
headers: dict.Dict(String, String),
algorithm: ChecksumAlgorithm,
body: BitArray,
) -> dict.Dict(String, String)
Add an x-amz-checksum-<algo> header to the request. Convenience
wrapper around checksum_header that lets call sites stay
pipeline-style with the existing Dict(String, String) header
shape — same ergonomics as with_content_md5_header.
pub fn with_checksum_header_for_wire(
headers: dict.Dict(String, String),
wire: String,
body: BitArray,
) -> dict.Dict(String, String)
Add the x-amz-checksum-<algo> header using a wire-form
algorithm name. Equivalent to
with_checksum_header(headers, checksum_algorithm_from_wire(wire), body).
Exists so the codegen can emit a single call that takes the
generated enum’s wire-encoder output directly, without
needing per-service algorithm-mapping helpers.
pub fn with_content_md5_header(
headers: dict.Dict(String, String),
body: BitArray,
) -> dict.Dict(String, String)
Set the Content-MD5 header to base64(md5(body)). Used by the
Smithy smithy.api#httpChecksumRequired trait — the codegen
emits a call to this helper at the tail of build_<op>_request
for any operation that carries the trait.
Always overwrites a previous Content-MD5 entry: the SDK is
responsible for the canonical value, and a stale caller-supplied
one would surface as a 400 from the service. Other headers pass
through unchanged.
MD5 is not a security primitive here. The wire contract requires it (S3-control + restJson1 protocol tests fix the exact bytes); SigV4 covers the actual auth on the request.
pub fn with_glacier_tree_hash_headers(
headers: dict.Dict(String, String),
body: BitArray,
) -> dict.Dict(String, String)
Glacier’s tree-hash + content-sha256 headers. Both end up as the Computed against the recursive 1 MiB chunk algorithm at https://docs.aws.amazon.com/amazonglacier/latest/dev/checksum- calculations.html: split the body into 1 MiB chunks, SHA-256 each, then pair-hash adjacent digests until one remains. Single-chunk bodies degenerate to plain SHA-256 (tree-hash == content-sha256), which is what every Glacier protocol-test fixture happens to use, but the recursive form is required for the > 1 MiB upload archive path used by real callers.
X-Amz-Sha256-Tree-Hash carries the tree-hash digest;
X-Amz-Content-Sha256 carries the full-body SHA-256. The Rust SDK
uses the same pair of headers in glacier_interceptors:: add_checksum_treehash. Both are skipped when already present so a
caller-supplied value wins.