[Crystal] Add request-signing seam (`Configuration#sign_request`)
Description
Adds a public request-signing seam to the crystal client generator. It lets a
consumer inject a per-request signature (OVH $1$+SHA1, AWS SigV4, RFC 9421, ...) without
subclassing or patching the generated code.
Why
Configuration#apply_auth! applies the static credentials declared in the OpenAPI spec
(apiKey / basic / bearer / oauth). A request signature is a hash computed per request over
the method, full URL, body and a timestamp — recomputed on every call. It is not expressible
as an OpenAPI security scheme, so apply_auth! cannot carry it and a procedural extension
point is needed.
How
Configuration gains an optional sign_request hook:
property sign_request : Proc(Symbol, String, String?, HTTP::Headers,
Hash(String, String | Array(String)), Nil)? = nil
Connection#request invokes it after apply_auth! and just before the Crest call, so
the hook sees the serialized body and the final method/URL and can mutate headers/query in
place. Left nil = no signing. apply_auth! is unchanged (fully backward compatible).
The Crest client has no middleware stack, so this differs in form from a Faraday middleware
pile — it is a single callback at the one point in Connection#request where everything a
signature needs is already in local scope.
Scope
Pure template change — no codegen Java. Touches configuration.mustache +
connection.mustache, adds a README section with an illustrative OVH example (and a note that
the hook runs before Crest re-encodes the query string), and regenerates the crystal and
crystal-qdrant samples. No OVH-specific code lives in the generator.
Testing
- New unit test
CrystalClientCodegenTest#testConfigurationExposesSignRequestSeam(red → green); full class 28 tests, 0 failures. - Regenerated samples: diff limited to
configuration.cr+connection.cr(+ README) in bothcrystalandcrystal-qdrant. The added lines arecrystal tool format-clean.
PR checklist
- Read the contribution guidelines.
- Rebuilt and regenerated the affected Crystal samples (
./bin/generate-samples.sh bin/configs/crystal.yaml bin/configs/crystal-qdrant.yaml). Only the Crystal generator's output changes. - @mention the technical committee for review.
cc @wing328 — small, backward-compatible extension point for the Crystal generator (request signing that OpenAPI security schemes cannot model).
Summary by cubic
Adds a request-signing hook to the Crystal client generator so consumers can compute per-request signatures (e.g., OVH, AWS SigV4, RFC 9421) without patching generated code. Backward compatible; static auth via apply_auth! is unchanged.
- New Features
- Added
Configuration#sign_requestProc(method, url, body, headers, query). - Invoked from
Connection#requestafterapply_auth!and before the Crest call; mutateheaders/queryto sign. - Off by default (
nil) with no behavior change. - Clarified docs:
urlexcludes the query string;bodyisnilfor form/multipart. Updated README with example and notes, added unit test, and regenerated Crystal and Qdrant samples.
- Added