Files
zip/headerparam_test.go
T
zeekayandHanzo Dev 08da1b6858 an operation can state its request facts and its success codes
Bridge exists in cloud because zip lacked two vocabularies. Both close here, and
both close the same way: the fact rides the op's CONTRACT, so every projection
sees it. A replacement that were equally invisible would not be one.

Gap 1 — a header tag. `Tenant string \`header:"X-Tenant"\`` binds off the wire
with no middleware anywhere, and appears as a header parameter in the document,
a flag on the command, and a property in the tool schema. Binding order is body,
then headers, then URL: the URL is the addressing authority. On a transport with
no HTTP request — the CLI, and the call plane — the answer is nothing rather
than a nil panic, which is the shape CallerOf already established.

Gap 2 — WithStatus takes a SET, and the answer states which one it is via
StatusCoder. The status is a property of the value the handler already returns,
so there is no mutable slot: a slot is a side channel and a side channel is what
Bridge was. Every declared code reaches the document, so a client has a branch
for each. A code the op did not declare is refused as an error — not a panic,
because it is a runtime value on a serving goroutine.

Also: App.Routes and App.Test now exist. Router's comment recommended both while
neither did, and they are the two things callers reached through Fiber() for —
so the stale reference is fixed by making it true rather than by deleting it.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-02 19:43:13 -07:00

63 lines
1.9 KiB
Go

package zip
import (
"context"
"encoding/json"
"testing"
)
type tenantIn struct {
Tenant string `json:"tenant" header:"X-Tenant"`
Name string `json:"name"`
}
type tenantOut struct {
Saw string `json:"saw"`
}
// Gap 1: a typed op reads a request header WITHOUT a middleware parking it in a
// context slot — and because it declares the header, every projection sees it.
func TestHeaderParam_DeclaredHeaderBindsAndIsPublished(t *testing.T) {
app := quiet("svc")
Post(app, "/v1/things", func(_ context.Context, in *tenantIn) (*tenantOut, error) {
return &tenantOut{Saw: in.Tenant}, nil
}, WithOperationID("things"))
// It binds off the wire, with no middleware installed anywhere.
req := postReq("/v1/things", "application/json", []byte(`{"name":"x"}`))
req.Header.Set("X-Tenant", "acme")
resp, err := app.Fiber().Test(req)
if err != nil {
t.Fatalf("POST: %v", err)
}
defer func() { _ = resp.Body.Close() }()
if body := readAll(t, resp.Body); body != `{"saw":"acme"}` {
t.Errorf("header did not reach the typed op: %s", body)
}
// And the DOCUMENT names it — the test a replacement for Bridge has to pass.
spec := app.OpenAPISpec()
post := spec["paths"].(map[string]map[string]any)["/v1/things"]["post"].(map[string]any)
raw, _ := json.Marshal(post["parameters"])
var params []map[string]any
_ = json.Unmarshal(raw, &params)
var found bool
for _, p := range params {
if p["name"] == "X-Tenant" && p["in"] == "header" {
found = true
}
}
if !found {
t.Errorf("the document does not declare the header parameter: %s", raw)
}
}
// Over a transport with no HTTP request the answer is honest — nothing — rather
// than a nil panic. Same shape CallerOf uses.
func TestHeaderParam_HonestOnATransportWithNoRequest(t *testing.T) {
var in tenantIn
bindHeaders(&in, nil) // the CLI's answer: there is no request to read
if in.Tenant != "" {
t.Errorf("bindHeaders invented a value with no request: %q", in.Tenant)
}
}