Skip to content

Commit 3338f93

Browse files
mromaszewiczclaude
andauthored
Strict server: gate no-content response headers on nullable/optional (#2351)
The no-content branch of the three strict-server interface templates (`strict-interface.tmpl`, `strict-fiber-interface.tmpl`, `strict-iris-interface.tmpl`) was rendering response headers unconditionally, missing the three-way `.IsNullable` / `.IsOptional` / default switch that PR #2301 added to the typed-body branch. Because the `{{$opid}}{{$statusCode}}ResponseHeaders` struct is shared between the typed-body and no-content branches and uses `{{.GoTypeDef}}` (since #2301 / #2331), an unset optional header field is `*string(nil)` and an unspecified nullable header is a zero `runtime.Nullable[T]`. The bare `fmt.Sprint(...)` in the no-content branch was therefore stringifying these to `<nil>` / a typed zero-value and emitting a junk header rather than omitting it. A 204-style response declaring an optional or nullable header — with the caller leaving it unset — produced a wrong header value instead of no header at all. Apply the same three-way switch to the no-content branch in all three templates so unset values are skipped, matching the typed-body branch behavior and matching what callers expect for OpenAPI `required: false` / `nullable: true` response headers. Add regression coverage: - `strict-schema.yaml` gains a `/no-content-headers` POST operation whose only response is 204 with `optional-header` (`required: false`) and `nullable-header` (`nullable: true`). - `NoContentHeaders` handler stub returning an empty `NoContentHeaders204Response{}` is wired into all seven framework server implementations (chi, echo, fiber, gin, gorilla, iris, stdhttp). - `NoContentHeadersOmitUnset` subtest added to the three `testImpl` copies (shared, stdhttp, fiber). Asserts both headers are absent from `rr.Header().Values(...)` when the response struct's header fields are left at their zero values. The shared `testImpl` covers chi, echo, gin, and iris in one place; stdhttp and fiber maintain their own copies because they live in separate test files (stdhttp because of its own go.mod, fiber because of its package boundary). Gorilla generates code but has no test driver — the handler stub is still required so the generated `StrictServerInterface` is satisfied. Fixes: #2349 Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 218effe commit 3338f93

22 files changed

Lines changed: 848 additions & 143 deletions

internal/test/strict-server/chi/server.gen.go

Lines changed: 100 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/test/strict-server/chi/server.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ func (s StrictServer) HeadersExample(ctx context.Context, request HeadersExample
122122
return HeadersExample200JSONResponse{Body: *request.Body, Headers: HeadersExample200ResponseHeaders{Header1: request.Params.Header1, Header2: *request.Params.Header2}}, nil
123123
}
124124

125+
func (s StrictServer) NoContentHeaders(ctx context.Context, request NoContentHeadersRequestObject) (NoContentHeadersResponseObject, error) {
126+
return NoContentHeaders204Response{}, nil
127+
}
128+
125129
func (s StrictServer) ReusableResponses(ctx context.Context, request ReusableResponsesRequestObject) (ReusableResponsesResponseObject, error) {
126130
return ReusableResponses200JSONResponse{ReusableresponseJSONResponse: ReusableresponseJSONResponse{Body: *request.Body}}, nil
127131
}

internal/test/strict-server/client/client.gen.go

Lines changed: 99 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)