From 2dc956fc81db87bfc27f34d23020126c58bfcda0 Mon Sep 17 00:00:00 2001 From: Marcin Romaszewicz Date: Thu, 9 Jul 2026 15:52:34 -0700 Subject: [PATCH 1/8] fix: gate fiber v3 auth scopes behind compatibility flag The fiber v3 server template emitted per-operation security scope context values unconditionally, but the corresponding ...Scopes constants are only generated when compatibility.enable-auth-scopes-on-context is set. Under default configuration, any spec with security requirements therefore produced code referencing undefined identifiers and failed to compile. Gate the emission behind the flag, matching fiber v2 and every other server backend. Co-Authored-By: Claude Fable 5 --- pkg/codegen/templates/fiber-v3/fiber-middleware.tmpl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/codegen/templates/fiber-v3/fiber-middleware.tmpl b/pkg/codegen/templates/fiber-v3/fiber-middleware.tmpl index 39cfdd708..122f958e4 100644 --- a/pkg/codegen/templates/fiber-v3/fiber-middleware.tmpl +++ b/pkg/codegen/templates/fiber-v3/fiber-middleware.tmpl @@ -47,9 +47,11 @@ func (siw *ServerInterfaceWrapper) {{$opid}}(c fiber.Ctx) error { {{end}} +{{if opts.Compatibility.EnableAuthScopesOnContext -}} {{range .SecurityDefinitions}} c.RequestCtx().SetUserValue(({{.ProviderName | sanitizeGoIdentity | ucFirst}}Scopes), {{toStringArray .Scopes}}) {{end}} +{{- end}} {{if .RequiresParamObject}} // Parameter object where we will unmarshal all parameters from the context From 2038062f9ef8b2831a87f2e8f2fdf74b3c3f9aae Mon Sep 17 00:00:00 2001 From: Marcin Romaszewicz Date: Thu, 9 Jul 2026 16:00:12 -0700 Subject: [PATCH 2/8] feat: add webhook/callback receivers for fiber v3 fiber v3 was the only server backend without webhook and callback receiver generation. Add a fiber-v3 receiver template (fiber v2's adapted to the v3 `fiber.Ctx` by-value interface signature), the GenerateFiberV3Receiver renderer, and codegen wiring for both webhook and callback operations. Also add internal/test/events/webhooks/fiberv3 for compile coverage, mirroring the other backends; this introduces gofiber/fiber/v3 as a dependency of the test-only internal/test module -- previously no fiber v3 output was compile-tested there at all. Co-Authored-By: Claude Fable 5 --- .../test/events/webhooks/fiberv3/config.yaml | 9 + internal/test/events/webhooks/fiberv3/doc.go | 6 + .../events/webhooks/fiberv3/webhooks.gen.go | 348 ++++++++++++++++++ internal/test/go.mod | 13 +- internal/test/go.sum | 32 +- pkg/codegen/codegen.go | 30 ++ pkg/codegen/operations.go | 8 + .../templates/fiber-v3/fiber-receiver.tmpl | 100 +++++ 8 files changed, 534 insertions(+), 12 deletions(-) create mode 100644 internal/test/events/webhooks/fiberv3/config.yaml create mode 100644 internal/test/events/webhooks/fiberv3/doc.go create mode 100644 internal/test/events/webhooks/fiberv3/webhooks.gen.go create mode 100644 pkg/codegen/templates/fiber-v3/fiber-receiver.tmpl diff --git a/internal/test/events/webhooks/fiberv3/config.yaml b/internal/test/events/webhooks/fiberv3/config.yaml new file mode 100644 index 000000000..edbb32d14 --- /dev/null +++ b/internal/test/events/webhooks/fiberv3/config.yaml @@ -0,0 +1,9 @@ +# yaml-language-server: $schema=../../../../../configuration-schema.json +package: fiberv3 +generate: + models: true + client: true + fiber-v3-server: true +output-options: + skip-prune: true +output: webhooks.gen.go diff --git a/internal/test/events/webhooks/fiberv3/doc.go b/internal/test/events/webhooks/fiberv3/doc.go new file mode 100644 index 000000000..06d15da29 --- /dev/null +++ b/internal/test/events/webhooks/fiberv3/doc.go @@ -0,0 +1,6 @@ +// Package webhooks_fiberv3 verifies that the fiber-v3-server flag +// emits a compilable WebhookReceiverInterface with fiber v3's +// (c fiber.Ctx) error signature. Compile-time assertion only. +package fiberv3 + +//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml ../spec.yaml diff --git a/internal/test/events/webhooks/fiberv3/webhooks.gen.go b/internal/test/events/webhooks/fiberv3/webhooks.gen.go new file mode 100644 index 000000000..01e1b443a --- /dev/null +++ b/internal/test/events/webhooks/fiberv3/webhooks.gen.go @@ -0,0 +1,348 @@ +// Package fiberv3 provides primitives to interact with the openapi HTTP API. +// +// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT. +package fiberv3 + +import ( + "bytes" + "context" + "encoding/json" + "io" + "net/http" + "net/url" + "strings" + + "github.com/gofiber/fiber/v3" +) + +// Defines values for PetStatusEventStatus. +const ( + Available PetStatusEventStatus = "available" + Pending PetStatusEventStatus = "pending" + Sold PetStatusEventStatus = "sold" +) + +// Valid indicates whether the value is a known member of the PetStatusEventStatus enum. +func (e PetStatusEventStatus) Valid() bool { + switch e { + case Available: + return true + case Pending: + return true + case Sold: + return true + default: + return false + } +} + +// PetStatusEvent defines model for PetStatusEvent. +type PetStatusEvent struct { + Id string `json:"id"` + Status PetStatusEventStatus `json:"status"` +} + +// PetStatusEventStatus defines model for PetStatusEvent.Status. +type PetStatusEventStatus string + +// PetStatusChangedJSONRequestBody defines body for PetStatusChanged for application/json ContentType. +type PetStatusChangedJSONRequestBody = PetStatusEvent + +// RequestEditorFn is the function signature for the RequestEditor callback function +type RequestEditorFn func(ctx context.Context, req *http.Request) error + +// Doer performs HTTP requests. +// +// The standard http.Client implements this interface. +type HttpRequestDoer interface { + Do(req *http.Request) (*http.Response, error) +} + +// Client which conforms to the OpenAPI3 specification for this service. +type Client struct { + // The endpoint of the server conforming to this interface, with scheme, + // https://api.deepmap.com for example. This can contain a path relative + // to the server, such as https://api.deepmap.com/dev-test, and all the + // paths in the swagger spec will be appended to the server. + Server string + + // Doer for performing requests, typically a *http.Client with any + // customized settings, such as certificate chains. + Client HttpRequestDoer + + // A list of callbacks for modifying requests which are generated before sending over + // the network. + RequestEditors []RequestEditorFn +} + +// ClientOption allows setting custom parameters during construction +type ClientOption func(*Client) error + +// Creates a new Client, with reasonable defaults +func NewClient(server string, opts ...ClientOption) (*Client, error) { + // create a client with sane default values + client := Client{ + Server: server, + } + // mutate client and add all optional params + for _, o := range opts { + if err := o(&client); err != nil { + return nil, err + } + } + // ensure the server URL always has a trailing slash + if !strings.HasSuffix(client.Server, "/") { + client.Server += "/" + } + // create httpClient, if not already present + if client.Client == nil { + client.Client = &http.Client{} + } + return &client, nil +} + +// WithHTTPClient allows overriding the default Doer, which is +// automatically created using http.Client. This is useful for tests. +func WithHTTPClient(doer HttpRequestDoer) ClientOption { + return func(c *Client) error { + c.Client = doer + return nil + } +} + +// WithRequestEditorFn allows setting up a callback function, which will be +// called right before sending the request. This can be used to mutate the request. +func WithRequestEditorFn(fn RequestEditorFn) ClientOption { + return func(c *Client) error { + c.RequestEditors = append(c.RequestEditors, fn) + return nil + } +} + +// The interface specification for the client above. +type ClientInterface interface { +} + +func (c *Client) applyEditors(ctx context.Context, req *http.Request, additionalEditors []RequestEditorFn) error { + for _, r := range c.RequestEditors { + if err := r(ctx, req); err != nil { + return err + } + } + for _, r := range additionalEditors { + if err := r(ctx, req); err != nil { + return err + } + } + return nil +} + +// ClientWithResponses builds on ClientInterface to offer response payloads +type ClientWithResponses struct { + ClientInterface +} + +// NewClientWithResponses creates a new ClientWithResponses, which wraps +// Client with return type handling +func NewClientWithResponses(server string, opts ...ClientOption) (*ClientWithResponses, error) { + client, err := NewClient(server, opts...) + if err != nil { + return nil, err + } + return &ClientWithResponses{client}, nil +} + +// WithBaseURL overrides the baseURL. +func WithBaseURL(baseURL string) ClientOption { + return func(c *Client) error { + newBaseURL, err := url.Parse(baseURL) + if err != nil { + return err + } + c.Server = newBaseURL.String() + return nil + } +} + +// ClientWithResponsesInterface is the interface specification for the client with responses above. +type ClientWithResponsesInterface interface { +} + +// WebhookInitiator sends OpenAPI 3.1 webhook requests to target URLs. +// Modeled on the generated Client, but with no stored Server -- the full +// target URL is provided per-call by the caller (typically discovered +// from a subscription registration). +type WebhookInitiator struct { + // Doer for performing requests, typically a *http.Client with any + // customized settings, such as certificate chains. + Client HttpRequestDoer + + // A list of callbacks for modifying requests which are generated before sending over + // the network. + RequestEditors []RequestEditorFn +} + +// WebhookInitiatorOption allows setting custom parameters during construction. +type WebhookInitiatorOption func(*WebhookInitiator) error + +// NewWebhookInitiator creates a new WebhookInitiator with reasonable defaults. +func NewWebhookInitiator(opts ...WebhookInitiatorOption) (*WebhookInitiator, error) { + initiator := WebhookInitiator{} + for _, o := range opts { + if err := o(&initiator); err != nil { + return nil, err + } + } + if initiator.Client == nil { + initiator.Client = &http.Client{} + } + return &initiator, nil +} + +// WithWebhookHTTPClient allows overriding the default Doer, which is +// automatically created using http.Client. This is useful for tests. +func WithWebhookHTTPClient(doer HttpRequestDoer) WebhookInitiatorOption { + return func(p *WebhookInitiator) error { + p.Client = doer + return nil + } +} + +// WithWebhookRequestEditorFn allows setting up a callback function, which +// will be called right before sending the webhook request. This can be +// used to mutate the request, e.g. to add signature headers. +func WithWebhookRequestEditorFn(fn RequestEditorFn) WebhookInitiatorOption { + return func(p *WebhookInitiator) error { + p.RequestEditors = append(p.RequestEditors, fn) + return nil + } +} + +func (p *WebhookInitiator) applyWebhookEditors(ctx context.Context, req *http.Request, additionalEditors []RequestEditorFn) error { + for _, r := range p.RequestEditors { + if err := r(ctx, req); err != nil { + return err + } + } + for _, r := range additionalEditors { + if err := r(ctx, req); err != nil { + return err + } + } + return nil +} + +// WebhookInitiatorInterface is the interface specification for the webhook initiator. +type WebhookInitiatorInterface interface { + // PetStatusChangedWithBody fires the petStatusChanged webhook with any body + PetStatusChangedWithBody(ctx context.Context, targetURL string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + + PetStatusChanged(ctx context.Context, targetURL string, body PetStatusChangedJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) +} + +func (p *WebhookInitiator) PetStatusChangedWithBody(ctx context.Context, targetURL string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewPetStatusChangedWebhookRequestWithBody(targetURL, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := p.applyWebhookEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return p.Client.Do(req) +} + +func (p *WebhookInitiator) PetStatusChanged(ctx context.Context, targetURL string, body PetStatusChangedJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewPetStatusChangedWebhookRequest(targetURL, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := p.applyWebhookEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return p.Client.Do(req) +} + +// NewPetStatusChangedWebhookRequest builds a application/json POST request for the petStatusChanged webhook +func NewPetStatusChangedWebhookRequest(targetURL string, body PetStatusChangedJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) + if err != nil { + return nil, err + } + bodyReader = bytes.NewReader(buf) + return NewPetStatusChangedWebhookRequestWithBody(targetURL, "application/json", bodyReader) +} + +// NewPetStatusChangedWebhookRequestWithBody builds a POST request for the petStatusChanged webhook with any body +func NewPetStatusChangedWebhookRequestWithBody(targetURL string, contentType string, body io.Reader) (*http.Request, error) { + var err error + _ = err + + reqURL, err := url.Parse(targetURL) + if err != nil { + return nil, err + } + + req, err := http.NewRequest(http.MethodPost, reqURL.String(), body) + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", contentType) + + return req, nil +} + +// ServerInterface represents all server handlers. +type ServerInterface interface { +} + +// ServerInterfaceWrapper converts contexts to parameters. +type ServerInterfaceWrapper struct { + Handler ServerInterface + HandlerMiddlewares []HandlerMiddlewareFunc +} + +type MiddlewareFunc fiber.Handler +type HandlerMiddlewareFunc func(c fiber.Ctx, next fiber.Handler) error + +// FiberServerOptions provides options for the Fiber server. +type FiberServerOptions struct { + BaseURL string + Middlewares []MiddlewareFunc + HandlerMiddlewares []HandlerMiddlewareFunc +} + +// RegisterHandlers creates http.Handler with routing matching OpenAPI spec. +func RegisterHandlers(router fiber.Router, si ServerInterface) { + RegisterHandlersWithOptions(router, si, FiberServerOptions{}) +} + +// RegisterHandlersWithOptions creates http.Handler with additional options +func RegisterHandlersWithOptions(router fiber.Router, si ServerInterface, options FiberServerOptions) { + +} + +// WebhookReceiverInterface represents handlers for receiving inbound +// webhook requests. Each webhook becomes a Handle*Webhook +// method that the implementation fills in. The caller mounts the per- +// webhook fiber.Handler returned by {Op}WebhookHandler at +// whatever URL path they advertise to senders. +type WebhookReceiverInterface interface { + // Notifies subscribers that a pet's status changed. + // HandlePetStatusChangedWebhook handles the POST webhook for petStatusChanged. + HandlePetStatusChangedWebhook(c fiber.Ctx) error +} + +// PetStatusChangedWebhookHandler returns the fiber.Handler for the petStatusChanged webhook. +// Mount this at the URL path advertised to webhook senders. Errors +// during parameter binding are returned via fiber.NewError so fiber's +// error chain reports them as 400. Per-handler middleware is not +// generated here; use fiber.App.Use() for engine-level middleware. +func PetStatusChangedWebhookHandler(si WebhookReceiverInterface) fiber.Handler { + return func(c fiber.Ctx) error { + return si.HandlePetStatusChangedWebhook(c) + } +} diff --git a/internal/test/go.mod b/internal/test/go.mod index 5fbe0b684..ebc09a69b 100644 --- a/internal/test/go.mod +++ b/internal/test/go.mod @@ -9,6 +9,7 @@ require ( github.com/gin-gonic/gin v1.12.0 github.com/go-chi/chi/v5 v5.2.5 github.com/gofiber/fiber/v2 v2.52.13 + github.com/gofiber/fiber/v3 v3.4.0 github.com/google/uuid v1.6.0 github.com/gorilla/mux v1.8.1 github.com/kataras/iris/v12 v12.2.11 @@ -29,7 +30,7 @@ require ( github.com/CloudyKit/jet/v6 v6.3.2 // indirect github.com/Joker/jade v1.1.3 // indirect github.com/Shopify/goreferrer v0.0.0-20250617153402-88c1d9a79b05 // indirect - github.com/andybalholm/brotli v1.2.1 // indirect + github.com/andybalholm/brotli v1.2.2 // indirect github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect github.com/aymerick/douceur v0.2.0 // indirect github.com/bytedance/gopkg v0.1.4 // indirect @@ -50,6 +51,8 @@ require ( github.com/go-playground/validator/v10 v10.30.2 // indirect github.com/goccy/go-json v0.10.6 // indirect github.com/goccy/go-yaml v1.19.2 // indirect + github.com/gofiber/schema v1.8.0 // indirect + github.com/gofiber/utils/v2 v2.1.1 // indirect github.com/golang/snappy v1.0.0 // indirect github.com/gomarkdown/markdown v0.0.0-20260417124207-7d523f7318df // indirect github.com/gorilla/css v1.0.1 // indirect @@ -61,13 +64,13 @@ require ( github.com/kataras/pio v0.0.13 // indirect github.com/kataras/sitemap v0.0.6 // indirect github.com/kataras/tunnel v0.0.4 // indirect - github.com/klauspost/compress v1.18.6 // indirect + github.com/klauspost/compress v1.19.0 // indirect github.com/klauspost/cpuid/v2 v2.3.0 // indirect github.com/labstack/gommon v0.5.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/mailgun/raymond/v2 v2.0.48 // indirect github.com/mailru/easyjson v0.9.2 // indirect - github.com/mattn/go-colorable v0.1.14 // indirect + github.com/mattn/go-colorable v0.1.15 // indirect github.com/mattn/go-isatty v0.0.22 // indirect github.com/mattn/go-runewidth v0.0.23 // indirect github.com/microcosm-cc/bluemonday v1.0.27 // indirect @@ -76,6 +79,7 @@ require ( github.com/oasdiff/yaml v0.1.0 // indirect github.com/oasdiff/yaml3 v0.0.13 // indirect github.com/pelletier/go-toml/v2 v2.3.0 // indirect + github.com/philhofer/fwd v1.2.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/quic-go/qpack v0.6.0 // indirect github.com/quic-go/quic-go v0.59.0 // indirect @@ -88,10 +92,11 @@ require ( github.com/stretchr/objx v0.5.2 // indirect github.com/tdewolff/minify/v2 v2.24.13 // indirect github.com/tdewolff/parse/v2 v2.8.12 // indirect + github.com/tinylib/msgp v1.6.4 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.3.1 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect - github.com/valyala/fasthttp v1.70.0 // indirect + github.com/valyala/fasthttp v1.72.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect diff --git a/internal/test/go.sum b/internal/test/go.sum index 40976f71c..68164a3eb 100644 --- a/internal/test/go.sum +++ b/internal/test/go.sum @@ -14,8 +14,8 @@ github.com/Shopify/goreferrer v0.0.0-20250617153402-88c1d9a79b05 h1:dG7/gLroJGht github.com/Shopify/goreferrer v0.0.0-20250617153402-88c1d9a79b05/go.mod h1:NYezi6wtnJtBm5btoprXc5SvAdqH0XTXWnUup0MptAI= github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= -github.com/andybalholm/brotli v1.2.1 h1:R+f5xP285VArJDRgowrfb9DqL18yVK0gKAW/F+eTWro= -github.com/andybalholm/brotli v1.2.1/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY= +github.com/andybalholm/brotli v1.2.2 h1:HzTuoo2ErYQqf5qvcJInB8uvqSVxRttzkFexPWtnceM= +github.com/andybalholm/brotli v1.2.2/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY= github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ= github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= @@ -53,6 +53,8 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/fxamacker/cbor/v2 v2.9.2 h1:X4Ksno9+x3cz0TZv69ec1hxP/+tymuR8PXQJyDwfh78= +github.com/fxamacker/cbor/v2 v2.9.2/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM= github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= github.com/getkin/kin-openapi v0.140.0 h1:JFn675aXRFjyiZKa/BFWploGldQlI0gobp4J5k0EZ2g= @@ -86,6 +88,12 @@ github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/gofiber/fiber/v2 v2.52.13 h1:TOKP64iqC9b5P49VrBW5tHhUOvDyrtJ0xePEfzJbCbk= github.com/gofiber/fiber/v2 v2.52.13/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw= +github.com/gofiber/fiber/v3 v3.4.0 h1:F0aND4vwZF7dR7cbvSwFQQEpBU902XHKWxrLsFBkVqw= +github.com/gofiber/fiber/v3 v3.4.0/go.mod h1:nAhJfdxUIJJph2tPWPmqWf8QDIN2iiqQiQf3lENZpdk= +github.com/gofiber/schema v1.8.0 h1:NGsC9toPHmj8Xg4KpznuXBzNmHG6V5YV0tXKpKMcmis= +github.com/gofiber/schema v1.8.0/go.mod h1:lmbXPQ8hvzXSLkdS2DS7pb4kpunC2Roh7Sj3HMjGfzA= +github.com/gofiber/utils/v2 v2.1.1 h1:kGnoGjwEnFW6w0x45W+kLlmMJvqBGkuUA4oMWKn/T/I= +github.com/gofiber/utils/v2 v2.1.1/go.mod h1:DdOgEVwQTi8cou/AKWPqhXOR4fHGRVhA/rEWL3IXG7Q= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -142,8 +150,8 @@ github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA= github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= -github.com/klauspost/compress v1.18.6 h1:2jupLlAwFm95+YDR+NwD2MEfFO9d4z4Prjl1XXDjuao= -github.com/klauspost/compress v1.18.6/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/klauspost/compress v1.19.0 h1:sXLILfc9jV2QYWkzFOPWStmcUVH2RHEB1JCdY2oVvCQ= +github.com/klauspost/compress v1.19.0/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -165,8 +173,8 @@ github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqA github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= github.com/mailru/easyjson v0.9.2 h1:dX8U45hQsZpxd80nLvDGihsQ/OxlvTkVUXH2r/8cb2M= github.com/mailru/easyjson v0.9.2/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= -github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= -github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= +github.com/mattn/go-colorable v0.1.15 h1:+u9SLTRGnXv73cEsnsmoZBom+dMU88B2M0aDcWy0/jY= +github.com/mattn/go-colorable v0.1.15/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4= github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4= github.com/mattn/go-runewidth v0.0.23 h1:7ykA0T0jkPpzSvMS5i9uoNn2Xy3R383f9HDx3RybWcw= @@ -209,6 +217,8 @@ github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/pelletier/go-toml/v2 v2.3.0 h1:k59bC/lIZREW0/iVaQR8nDHxVq8OVlIzYCOJf421CaM= github.com/pelletier/go-toml/v2 v2.3.0/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM= +github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -228,6 +238,8 @@ github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiy github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/shamaton/msgpack/v3 v3.1.2 h1:d5gWAIyMU4M0WgDjz6IFSCuXJUA2dFwRHBpDclE8CLw= +github.com/shamaton/msgpack/v3 v3.1.2/go.mod h1:DcQG8jrdrQCIxr3HlMYkiXdMhK+KfN2CitkyzsQV4uc= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= @@ -259,14 +271,16 @@ github.com/tdewolff/parse/v2 v2.8.12/go.mod h1:Hwlni2tiVNKyzR1o6nUs4FOF07URA+JLB github.com/tdewolff/test v1.0.11/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= github.com/tdewolff/test v1.0.12 h1:7F21DqIajswxuche0geHdrUZRCWE4oko4b7bcmkkrxk= github.com/tdewolff/test v1.0.12/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8= +github.com/tinylib/msgp v1.6.4 h1:mOwYbyYDLPj35mkA2BjjYejgJk9BuHxDdvRnb6v2ZcQ= +github.com/tinylib/msgp v1.6.4/go.mod h1:RSp0LW9oSxFut3KzESt5Voq4GVWyS+PSulT77roAqEA= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go/codec v1.3.1 h1:waO7eEiFDwidsBN6agj1vJQ4AG7lh2yqXyOXqhgQuyY= github.com/ugorji/go/codec v1.3.1/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.70.0 h1:LAhMGcWk13QZWm85+eg8ZBNbrq5mnkWFGbHMUJHIdXA= -github.com/valyala/fasthttp v1.70.0/go.mod h1:oDZEHHkJ/Buyklg6uURmYs19442zFSnCIfX3j1FY3pE= +github.com/valyala/fasthttp v1.72.0 h1:R7kYdoWhn1ye1fVpP+cDHDJwYm3NkwLliwgzJ/Abg7M= +github.com/valyala/fasthttp v1.72.0/go.mod h1:zsbLTYqcpIktdQytlVBwIjY9La5d6bs990nBxWg8efk= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= @@ -275,6 +289,8 @@ github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAh github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/vmware-labs/yaml-jsonpath v0.3.2 h1:/5QKeCBGdsInyDCyVNLbXyilb61MXGi9NP674f9Hobk= github.com/vmware-labs/yaml-jsonpath v0.3.2/go.mod h1:U6whw1z03QyqgWdgXxvVnQ90zN1BWz5V+51Ewf8k+rQ= +github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= diff --git a/pkg/codegen/codegen.go b/pkg/codegen/codegen.go index 092e2e1b6..ea29b723e 100644 --- a/pkg/codegen/codegen.go +++ b/pkg/codegen/codegen.go @@ -557,6 +557,15 @@ func Generate(spec *openapi3.T, opts Configuration) (string, error) { } } + // Webhook receiver (fiber v3) -- (c fiber.Ctx) error signature. + var fiberV3WebhookReceiverOut string + if opts.Generate.FiberV3Server && len(webhookOps) > 0 { + fiberV3WebhookReceiverOut, err = GenerateFiberV3Receiver(t, "Webhook", webhookOps) + if err != nil { + return "", fmt.Errorf("error generating fiber v3 webhook receiver: %w", err) + } + } + // Webhook receiver (iris) -- (ctx iris.Context) signature. var irisWebhookReceiverOut string if opts.Generate.IrisServer && len(webhookOps) > 0 { @@ -642,6 +651,15 @@ func Generate(spec *openapi3.T, opts Configuration) (string, error) { } } + // Callback receiver (fiber v3). + var fiberV3CallbackReceiverOut string + if opts.Generate.FiberV3Server && len(callbackOps) > 0 { + fiberV3CallbackReceiverOut, err = GenerateFiberV3Receiver(t, "Callback", callbackOps) + if err != nil { + return "", fmt.Errorf("error generating fiber v3 callback receiver: %w", err) + } + } + // Callback receiver (iris). var irisCallbackReceiverOut string if opts.Generate.IrisServer && len(callbackOps) > 0 { @@ -816,6 +834,18 @@ func Generate(spec *openapi3.T, opts Configuration) (string, error) { if err != nil { return "", fmt.Errorf("error writing server path handlers: %w", err) } + if fiberV3WebhookReceiverOut != "" { + _, err = w.WriteString(fiberV3WebhookReceiverOut) + if err != nil { + return "", fmt.Errorf("error writing fiber v3 webhook receiver: %w", err) + } + } + if fiberV3CallbackReceiverOut != "" { + _, err = w.WriteString(fiberV3CallbackReceiverOut) + if err != nil { + return "", fmt.Errorf("error writing fiber v3 callback receiver: %w", err) + } + } } if opts.Generate.GinServer { diff --git a/pkg/codegen/operations.go b/pkg/codegen/operations.go index af64daf8f..2235c5ceb 100644 --- a/pkg/codegen/operations.go +++ b/pkg/codegen/operations.go @@ -2029,6 +2029,14 @@ func GenerateFiberReceiver(t *template.Template, prefix string, ops []OperationD return GenerateTemplates([]string{"fiber/fiber-receiver.tmpl"}, t, NewReceiverTemplateData(prefix, ops)) } +// GenerateFiberV3Receiver renders the fiber (v3) receiver template. +// Same shape as v2 but with `fiber.Ctx` (interface, by value) -- the +// only API difference between fiber v2 and v3 that affects the +// receiver. +func GenerateFiberV3Receiver(t *template.Template, prefix string, ops []OperationDefinition) (string, error) { + return GenerateTemplates([]string{"fiber-v3/fiber-receiver.tmpl"}, t, NewReceiverTemplateData(prefix, ops)) +} + // GenerateIrisReceiver renders the iris receiver template. Iris's // handler shape is `(ctx iris.Context)` (no error return); binding // errors set ctx.StatusCode(400) plus ctx.WriteString and return. diff --git a/pkg/codegen/templates/fiber-v3/fiber-receiver.tmpl b/pkg/codegen/templates/fiber-v3/fiber-receiver.tmpl new file mode 100644 index 000000000..f28d2bdf4 --- /dev/null +++ b/pkg/codegen/templates/fiber-v3/fiber-receiver.tmpl @@ -0,0 +1,100 @@ +// {{.Prefix}}ReceiverInterface represents handlers for receiving inbound +// {{.PrefixLower}} requests. Each {{.PrefixLower}} becomes a Handle*{{.Prefix}} +// method that the implementation fills in. The caller mounts the per- +// {{.PrefixLower}} fiber.Handler returned by {Op}{{.Prefix}}Handler at +// whatever URL path they advertise to senders. +type {{.Prefix}}ReceiverInterface interface { +{{range .Operations -}} +{{.SummaryAsComment ""}} +// Handle{{.OperationId}}{{$.Prefix}} handles the {{.Method}} {{$.PrefixLower}} for {{.SourceName}}. +Handle{{.OperationId}}{{$.Prefix}}(c fiber.Ctx{{if .RequiresParamObject}}, params {{.OperationId}}Params{{end}}) error +{{end}} +} + +{{range .Operations -}} +{{$opid := .OperationId -}} +{{$srcName := .SourceName -}} +// {{$opid}}{{$.Prefix}}Handler returns the fiber.Handler for the {{$srcName}} {{$.PrefixLower}}. +// Mount this at the URL path advertised to {{$.PrefixLower}} senders. Errors +// during parameter binding are returned via fiber.NewError so fiber's +// error chain reports them as 400. Per-handler middleware is not +// generated here; use fiber.App.Use() for engine-level middleware. +func {{$opid}}{{$.Prefix}}Handler(si {{$.Prefix}}ReceiverInterface) fiber.Handler { + return func(c fiber.Ctx) error { +{{- if .RequiresParamObject}} + var err error + _ = err + + // Parameter object where we will unmarshal all parameters from the context. + var params {{$opid}}Params +{{if .QueryParams}} + var query url.Values + query, err = url.ParseQuery(string(c.Request().URI().QueryString())) + if err != nil { + return fiber.NewError(fiber.StatusBadRequest, fmt.Errorf("Invalid format for query string: %w", err).Error()) + } +{{end}} +{{range $paramIdx, $param := .QueryParams}} + // ------------- {{if .Required}}Required{{else}}Optional{{end}} query parameter "{{.ParamName}}" ------------- + {{if .IsStyled}} + err = runtime.BindQueryParameterWithOptions("{{.Style}}", {{.Explode}}, {{.Required}}, "{{.ParamName}}", query, ¶ms.{{.GoName}}, runtime.BindQueryParameterOptions{Type: "{{.SchemaType}}", Format: "{{.SchemaFormat}}"}) + if err != nil { + return fiber.NewError(fiber.StatusBadRequest, fmt.Errorf("Invalid format for parameter {{.ParamName}}: %w", err).Error()) + } + {{else}} + if paramValue := c.Query("{{.ParamName}}"); paramValue != "" { + {{if .IsPassThrough}} + params.{{.GoName}} = {{if .HasOptionalPointer}}&{{end}}paramValue + {{end}} + {{if .IsJson}} + var value {{.TypeDef}} + err = json.Unmarshal([]byte(paramValue), &value) + if err != nil { + return fiber.NewError(fiber.StatusBadRequest, fmt.Errorf("Error unmarshaling parameter '{{.ParamName}}' as JSON: %w", err).Error()) + } + params.{{.GoName}} = {{if .HasOptionalPointer}}&{{end}}value + {{end}} + }{{if .Required}} else { + return fiber.NewError(fiber.StatusBadRequest, "Query argument {{.ParamName}} is required, but not found") + }{{end}} + {{end}} +{{end}} +{{if .HeaderParams}} + headers := c.GetReqHeaders() +{{range $paramIdx, $param := .HeaderParams}} + // ------------- {{if .Required}}Required{{else}}Optional{{end}} header parameter "{{.ParamName}}" ------------- + if valueList, found := headers[http.CanonicalHeaderKey("{{.ParamName}}")]; found { + var {{.GoName}} {{.TypeDef}} + n := len(valueList) + if n != 1 { + return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Too many values for header {{.ParamName}}, 1 is required, but %d found", n)) + } + {{if .IsPassThrough}} + {{.GoName}} = valueList[0] + params.{{.GoName}} = {{if .HasOptionalPointer}}&{{end}}{{.GoName}} + {{end}} + {{if .IsJson}} + err = json.Unmarshal([]byte(valueList[0]), &{{.GoName}}) + if err != nil { + return fiber.NewError(fiber.StatusBadRequest, fmt.Errorf("Error unmarshaling parameter '{{.ParamName}}' as JSON: %w", err).Error()) + } + params.{{.GoName}} = {{if .HasOptionalPointer}}&{{end}}{{.GoName}} + {{end}} + {{if .IsStyled}} + err = runtime.BindStyledParameterWithOptions("{{.Style}}", "{{.ParamName}}", valueList[0], &{{.GoName}}, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationHeader, Explode: {{.Explode}}, Required: {{.Required}}, Type: "{{.SchemaType}}", Format: "{{.SchemaFormat}}"}) + if err != nil { + return fiber.NewError(fiber.StatusBadRequest, fmt.Errorf("Invalid format for parameter {{.ParamName}}: %w", err).Error()) + } + params.{{.GoName}} = {{if .HasOptionalPointer}}&{{end}}{{.GoName}} + {{end}} + }{{if .Required}} else { + return fiber.NewError(fiber.StatusBadRequest, "Header parameter {{.ParamName}} is required, but not found") + }{{end}} +{{end}} +{{end}} +{{- end}} + return si.Handle{{$opid}}{{$.Prefix}}(c{{if .RequiresParamObject}}, params{{end}}) + } +} + +{{end}} From d1a6b4e8e39b8659ad0089468313bacac4ce2af3 Mon Sep 17 00:00:00 2001 From: Marcin Romaszewicz Date: Thu, 9 Jul 2026 16:05:08 -0700 Subject: [PATCH 3/8] fix: apply IrisServerOptions.Middlewares in iris server The iris RegisterHandlersWithOptions declared a Middlewares option but never read it, so user-supplied middlewares were silently ignored. Apply them via router.Use() before route registration, matching how fiber treats its equivalent Middlewares option. The loop sits outside the operations guard so middlewares register even for a spec with no operations. Adds a runtime regression test under internal/test/servers/middleware, which fails against the previous template. Co-Authored-By: Claude Fable 5 --- examples/minimal-server/iris/api/ping.gen.go | 3 + .../iris/api/petstore-server.gen.go | 3 + .../test/events/webhooks/iris/webhooks.gen.go | 3 + .../roundtrip/iris/gen/server.gen.go | 3 + .../test/servers/middleware/iris/config.yaml | 6 ++ internal/test/servers/middleware/iris/doc.go | 3 + .../test/servers/middleware/iris/main_test.go | 41 ++++++++++++++ .../servers/middleware/iris/middleware.gen.go | 55 +++++++++++++++++++ .../test/servers/middleware/iris/spec.yaml | 11 ++++ .../servers/routers/smoke/iris/out.gen.go | 3 + .../test/servers/strict/iris/server.gen.go | 3 + .../iris/serversstrictmulticontentiris.gen.go | 3 + pkg/codegen/templates/iris/iris-handler.tmpl | 4 ++ 13 files changed, 141 insertions(+) create mode 100644 internal/test/servers/middleware/iris/config.yaml create mode 100644 internal/test/servers/middleware/iris/doc.go create mode 100644 internal/test/servers/middleware/iris/main_test.go create mode 100644 internal/test/servers/middleware/iris/middleware.gen.go create mode 100644 internal/test/servers/middleware/iris/spec.yaml diff --git a/examples/minimal-server/iris/api/ping.gen.go b/examples/minimal-server/iris/api/ping.gen.go index 3ef88437f..8f92a5327 100644 --- a/examples/minimal-server/iris/api/ping.gen.go +++ b/examples/minimal-server/iris/api/ping.gen.go @@ -47,6 +47,9 @@ func RegisterHandlers(router *iris.Application, si ServerInterface) { // RegisterHandlersWithOptions creates http.Handler with additional options func RegisterHandlersWithOptions(router *iris.Application, si ServerInterface, options IrisServerOptions) { + for _, m := range options.Middlewares { + router.Use(m) + } wrapper := ServerInterfaceWrapper{ Handler: si, diff --git a/examples/petstore-expanded/iris/api/petstore-server.gen.go b/examples/petstore-expanded/iris/api/petstore-server.gen.go index 9846a1b10..9c200a97a 100644 --- a/examples/petstore-expanded/iris/api/petstore-server.gen.go +++ b/examples/petstore-expanded/iris/api/petstore-server.gen.go @@ -173,6 +173,9 @@ func RegisterHandlers(router *iris.Application, si ServerInterface) { // RegisterHandlersWithOptions creates http.Handler with additional options func RegisterHandlersWithOptions(router *iris.Application, si ServerInterface, options IrisServerOptions) { + for _, m := range options.Middlewares { + router.Use(m) + } wrapper := ServerInterfaceWrapper{ Handler: si, diff --git a/internal/test/events/webhooks/iris/webhooks.gen.go b/internal/test/events/webhooks/iris/webhooks.gen.go index 2be798980..a7008cdfe 100644 --- a/internal/test/events/webhooks/iris/webhooks.gen.go +++ b/internal/test/events/webhooks/iris/webhooks.gen.go @@ -319,6 +319,9 @@ func RegisterHandlers(router *iris.Application, si ServerInterface) { // RegisterHandlersWithOptions creates http.Handler with additional options func RegisterHandlersWithOptions(router *iris.Application, si ServerInterface, options IrisServerOptions) { + for _, m := range options.Middlewares { + router.Use(m) + } router.Build() } diff --git a/internal/test/parameters/roundtrip/iris/gen/server.gen.go b/internal/test/parameters/roundtrip/iris/gen/server.gen.go index 2da66aeed..cdf8aae2b 100644 --- a/internal/test/parameters/roundtrip/iris/gen/server.gen.go +++ b/internal/test/parameters/roundtrip/iris/gen/server.gen.go @@ -996,6 +996,9 @@ func RegisterHandlers(router *iris.Application, si ServerInterface) { // RegisterHandlersWithOptions creates http.Handler with additional options func RegisterHandlersWithOptions(router *iris.Application, si ServerInterface, options IrisServerOptions) { + for _, m := range options.Middlewares { + router.Use(m) + } wrapper := ServerInterfaceWrapper{ Handler: si, diff --git a/internal/test/servers/middleware/iris/config.yaml b/internal/test/servers/middleware/iris/config.yaml new file mode 100644 index 000000000..be1895acb --- /dev/null +++ b/internal/test/servers/middleware/iris/config.yaml @@ -0,0 +1,6 @@ +# yaml-language-server: $schema=../../../../../configuration-schema.json +package: serversmiddlewareiris +generate: + iris-server: true + models: true +output: middleware.gen.go diff --git a/internal/test/servers/middleware/iris/doc.go b/internal/test/servers/middleware/iris/doc.go new file mode 100644 index 000000000..7908ac672 --- /dev/null +++ b/internal/test/servers/middleware/iris/doc.go @@ -0,0 +1,3 @@ +package serversmiddlewareiris + +//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml spec.yaml diff --git a/internal/test/servers/middleware/iris/main_test.go b/internal/test/servers/middleware/iris/main_test.go new file mode 100644 index 000000000..a9e19caf0 --- /dev/null +++ b/internal/test/servers/middleware/iris/main_test.go @@ -0,0 +1,41 @@ +package serversmiddlewareiris + +import ( + "net/http" + "net/http/httptest" + "testing" + + "github.com/kataras/iris/v12" + "github.com/stretchr/testify/assert" +) + +type impl struct{} + +// (GET /test) +func (i *impl) Test(ctx iris.Context) { + ctx.StatusCode(http.StatusOK) +} + +// IrisServerOptions.Middlewares used to be silently ignored by +// RegisterHandlersWithOptions; this asserts they actually run. +func TestMiddlewaresAreApplied(t *testing.T) { + server := &impl{} + + calls := 0 + app := iris.New() + RegisterHandlersWithOptions(app, server, IrisServerOptions{ + Middlewares: []MiddlewareFunc{ + func(ctx iris.Context) { + calls++ + ctx.Next() + }, + }, + }) + + req := httptest.NewRequest(http.MethodGet, "/test", nil) + rec := httptest.NewRecorder() + app.ServeHTTP(rec, req) + + assert.Equal(t, http.StatusOK, rec.Code) + assert.Equal(t, 1, calls) +} diff --git a/internal/test/servers/middleware/iris/middleware.gen.go b/internal/test/servers/middleware/iris/middleware.gen.go new file mode 100644 index 000000000..8086e994a --- /dev/null +++ b/internal/test/servers/middleware/iris/middleware.gen.go @@ -0,0 +1,55 @@ +// Package serversmiddlewareiris provides primitives to interact with the openapi HTTP API. +// +// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.0.0-00010101000000-000000000000 DO NOT EDIT. +package serversmiddlewareiris + +import ( + "github.com/kataras/iris/v12" +) + +// ServerInterface represents all server handlers. +type ServerInterface interface { + + // (GET /test) + Test(ctx iris.Context) +} + +// ServerInterfaceWrapper converts echo contexts to parameters. +type ServerInterfaceWrapper struct { + Handler ServerInterface +} + +type MiddlewareFunc iris.Handler + +// Test converts iris context to params. +func (w *ServerInterfaceWrapper) Test(ctx iris.Context) { + + // Invoke the callback with all the unmarshaled arguments + w.Handler.Test(ctx) +} + +// IrisServerOption is the option for iris server +type IrisServerOptions struct { + BaseURL string + Middlewares []MiddlewareFunc +} + +// RegisterHandlers creates http.Handler with routing matching OpenAPI spec. +func RegisterHandlers(router *iris.Application, si ServerInterface) { + RegisterHandlersWithOptions(router, si, IrisServerOptions{}) +} + +// RegisterHandlersWithOptions creates http.Handler with additional options +func RegisterHandlersWithOptions(router *iris.Application, si ServerInterface, options IrisServerOptions) { + for _, m := range options.Middlewares { + router.Use(m) + } + + wrapper := ServerInterfaceWrapper{ + Handler: si, + } + + router.Get(options.BaseURL+"/test", wrapper.Test) + + router.Build() +} diff --git a/internal/test/servers/middleware/iris/spec.yaml b/internal/test/servers/middleware/iris/spec.yaml new file mode 100644 index 000000000..a5c46d286 --- /dev/null +++ b/internal/test/servers/middleware/iris/spec.yaml @@ -0,0 +1,11 @@ +openapi: "3.0.1" +info: + title: Iris middleware test + version: 1.0.0 +paths: + /test: + get: + operationId: test + responses: + 200: + description: good diff --git a/internal/test/servers/routers/smoke/iris/out.gen.go b/internal/test/servers/routers/smoke/iris/out.gen.go index d57447cba..054e264f7 100644 --- a/internal/test/servers/routers/smoke/iris/out.gen.go +++ b/internal/test/servers/routers/smoke/iris/out.gen.go @@ -95,6 +95,9 @@ func RegisterHandlers(router *iris.Application, si ServerInterface) { // RegisterHandlersWithOptions creates http.Handler with additional options func RegisterHandlersWithOptions(router *iris.Application, si ServerInterface, options IrisServerOptions) { + for _, m := range options.Middlewares { + router.Use(m) + } wrapper := ServerInterfaceWrapper{ Handler: si, diff --git a/internal/test/servers/strict/iris/server.gen.go b/internal/test/servers/strict/iris/server.gen.go index ca61a4906..3de9ea6cd 100644 --- a/internal/test/servers/strict/iris/server.gen.go +++ b/internal/test/servers/strict/iris/server.gen.go @@ -283,6 +283,9 @@ func RegisterHandlers(router *iris.Application, si ServerInterface) { // RegisterHandlersWithOptions creates http.Handler with additional options func RegisterHandlersWithOptions(router *iris.Application, si ServerInterface, options IrisServerOptions) { + for _, m := range options.Middlewares { + router.Use(m) + } wrapper := ServerInterfaceWrapper{ Handler: si, diff --git a/internal/test/servers/strict/multicontent/iris/serversstrictmulticontentiris.gen.go b/internal/test/servers/strict/multicontent/iris/serversstrictmulticontentiris.gen.go index 30c51c90e..c7093ed8a 100644 --- a/internal/test/servers/strict/multicontent/iris/serversstrictmulticontentiris.gen.go +++ b/internal/test/servers/strict/multicontent/iris/serversstrictmulticontentiris.gen.go @@ -331,6 +331,9 @@ func RegisterHandlers(router *iris.Application, si ServerInterface) { // RegisterHandlersWithOptions creates http.Handler with additional options func RegisterHandlersWithOptions(router *iris.Application, si ServerInterface, options IrisServerOptions) { + for _, m := range options.Middlewares { + router.Use(m) + } wrapper := ServerInterfaceWrapper{ Handler: si, diff --git a/pkg/codegen/templates/iris/iris-handler.tmpl b/pkg/codegen/templates/iris/iris-handler.tmpl index f2fb56e44..795cf4f10 100644 --- a/pkg/codegen/templates/iris/iris-handler.tmpl +++ b/pkg/codegen/templates/iris/iris-handler.tmpl @@ -12,6 +12,10 @@ func RegisterHandlers(router *iris.Application, si ServerInterface) { // RegisterHandlersWithOptions creates http.Handler with additional options func RegisterHandlersWithOptions(router *iris.Application, si ServerInterface, options IrisServerOptions) { + for _, m := range options.Middlewares { + router.Use(m) + } + {{if .}} wrapper := ServerInterfaceWrapper{ Handler: si, From beeb5efff1c25435a0a075a2ef21f720a60458d4 Mon Sep 17 00:00:00 2001 From: Marcin Romaszewicz Date: Thu, 9 Jul 2026 16:14:12 -0700 Subject: [PATCH 4/8] fix: stop clobbering pass-through header params All nine server wrapper templates bound a pass-through (non-JSON content) header param by assigning params.X directly, then unconditionally re-assigned params.X from a local variable that the pass-through branch never set -- so the handler always received the zero value. The JSON and styled branches bind through the local, which is why the trailing assignment exists. Assign the local in the pass-through branch instead, letting the shared trailing assignment (and its optional-pointer handling) apply uniformly to all three branches. The receiver templates already did this correctly; the wrappers never got the same shape. Adds a text/plain content header param to the parameter round-trip suite, which fails on every backend without this fix. Co-Authored-By: Claude Fable 5 --- .../roundtrip/chi/gen/server.gen.go | 59 ++++++++++++------- .../parameters/roundtrip/chi/gen/types.gen.go | 3 + .../roundtrip/client/gen/client.gen.go | 17 +++++- .../roundtrip/echo/gen/server.gen.go | 56 +++++++++++------- .../roundtrip/echo/gen/types.gen.go | 3 + .../roundtrip/echov5/gen/server.gen.go | 56 +++++++++++------- .../roundtrip/echov5/gen/types.gen.go | 3 + .../roundtrip/fiber/gen/server.gen.go | 58 +++++++++++------- .../roundtrip/fiber/gen/types.gen.go | 3 + .../roundtrip/gin/gen/server.gen.go | 59 ++++++++++++------- .../parameters/roundtrip/gin/gen/types.gen.go | 3 + .../roundtrip/gorilla/gen/server.gen.go | 59 ++++++++++++------- .../roundtrip/gorilla/gen/types.gen.go | 3 + .../roundtrip/iris/gen/server.gen.go | 58 +++++++++++------- .../roundtrip/iris/gen/types.gen.go | 3 + .../roundtrip/param_roundtrip_test.go | 15 +++++ .../test/parameters/roundtrip/parameters.yaml | 8 +++ .../roundtrip/stdhttp/gen/server.gen.go | 59 ++++++++++++------- .../roundtrip/stdhttp/gen/types.gen.go | 3 + pkg/codegen/templates/chi/chi-middleware.tmpl | 2 +- pkg/codegen/templates/echo/echo-wrappers.tmpl | 2 +- .../templates/echo/v5/echo-wrappers.tmpl | 2 +- .../templates/fiber-v3/fiber-middleware.tmpl | 2 +- .../templates/fiber/fiber-middleware.tmpl | 2 +- pkg/codegen/templates/gin/gin-wrappers.tmpl | 2 +- .../templates/gorilla/gorilla-middleware.tmpl | 2 +- .../templates/iris/iris-middleware.tmpl | 2 +- .../stdhttp/std-http-middleware.tmpl | 2 +- 28 files changed, 358 insertions(+), 188 deletions(-) diff --git a/internal/test/parameters/roundtrip/chi/gen/server.gen.go b/internal/test/parameters/roundtrip/chi/gen/server.gen.go index a32748c70..82513e7f2 100644 --- a/internal/test/parameters/roundtrip/chi/gen/server.gen.go +++ b/internal/test/parameters/roundtrip/chi/gen/server.gen.go @@ -605,6 +605,21 @@ func (siw *ServerInterfaceWrapper) GetHeader(w http.ResponseWriter, r *http.Requ } + // ------------- Optional header parameter "X-Pass-Through" ------------- + if valueList, found := headers[http.CanonicalHeaderKey("X-Pass-Through")]; found { + var XPassThrough string + n := len(valueList) + if n != 1 { + siw.ErrorHandlerFunc(w, r, &TooManyValuesForParamError{ParamName: "X-Pass-Through", Count: n}) + return + } + + XPassThrough = valueList[0] + + params.XPassThrough = &XPassThrough + + } + // ------------- Optional header parameter "1-Starting-With-Number" ------------- if valueList, found := headers[http.CanonicalHeaderKey("1-Starting-With-Number")]; found { var N1StartingWithNumber string @@ -1568,28 +1583,28 @@ func HandlerWithOptions(si ServerInterface, options ChiServerOptions) http.Handl // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "3FpLb+M2F/0rwv2+VaFYdqYrdRVMp22ATiatA0yBIAtGuo44lUQOSacJDP33gpRkPa2HLeXRXWJd3sch", - "z6F4qR14LOIsxlhJcHcgUHIWSzT/rGnEQ/wz+0n/4rFYYaz0nwqflMNDQmP9n/QCjIj5/ZkjuCCVoPED", - "JElig4/SE5QrymJw4cKSxq+Vx7LY/Tf0FGjT1I+J/pFpq6cv6UN3B1wwjkLRNLlLvxSNxgofUEBiw6W8", - "8KM0qezhPWMhklg/LJz9X+AGXPifU9TvZMGdL0U+Ar9vqUAf3Nt8sK1DF3HuKm6rOW6okOqKRNgCjA2C", - "hW0PalGNlV1ydWcwpfGG6cEh9TCbnNgEgs+XN9q7okq7hxuUylqjeEQBNjyikOk0rBbLxVIbMo4x4RRc", - "+LBYLlZgAycqMPk72Xyn9Tk7TgSJEv3kAU25ulii51XPBvyK6mN5gHElSIQKhQT3trJ+COch9cxg55tk", - "tVXUNT3VhZGhAa5JG+wcBhMZylgqscXkzq6u8fPl8lC8vZ1TI0JiYjoeY39T7EbDWDRgqBKCCxpRRR+1", - "IT7xkPkI7oaEErPCvNxNXhrYJag2TEREpST4cA52gxOJPSiihudAQDw5YhbFt4gQ5HloWFIJSxVGclD8", - "/S9ptJZ8Gml04T1fGntYWE6YQbiwSkLDpKweuhmxC4LjIs5F92olXmpQYNhagcegCYJ+ZklFhKLxg/UP", - "VYEVb6N7I5WtXlayAkRduuvq4uOGbEN1rMJgvE2XWqvAfIq30bUWFtmnMNf5w7RE7dZ6JOEWZV7n9y2K", - "59IKM65VcJ2JaFGxfgLu7Wq5tM+Xyzt7gBg0JffHFJvKTDArXy1Z8QESH0WXvP6WWpwqr0HuJiv+r7Pr", - "0pBZhbYj9NmnTBteRHqbiVxo6/YkXkyID2T1ynLczCrVpnaw5lDnQxm8O5FuFpI5ygs6QrLrPldn68z6", - "7CtVwdlVbv1iMh6SewyzxWEWsLNbGMn6ofNd+vf6sKbStS3PIa/B0xDIBqmezSHDVAhTvlyXMcuPH2NB", - "O3QKmQK1Iex6KXz2e8Z4iMo73QwoDVhSM0N0xdqI149PdVwHOmVd/g9Rb19/lXwjgOtl3ynIvQn6NXjX", - "j84Qvp2Cy6sSLiJK0Kca36jfrUafG4OOkSLqz060tLr5ANsTbRRix+9xPZCNY9jc4JSo9tMofE7a4Hog", - "GkG22fBp7G/UHwDOBLvbe2Zcc3Mbh9oJW9v7YF2VbgOgOW1fe9M840TKm0Cw7UMw5AbkujDvvP8YcX/2", - "KrcbpiP4MyIvLrcOlVyy6unF+Yi8u7lSa0T6qeujOVPrSxQLxS9ynvq4nyEXakag3wXcH1XLHvAkJx5a", - "fm5udbbOajjKqe4wCgRNOkXyLc1Pyo9Nl0+frs6mlO3UTPmFiah3qo1RzywPatfW2/XTw6WHwsh2bS2r", - "F0tqWNu2jtn8l2i1iFME3Jfad7NQr3aeO+MuCk8W0Mr2wgNxum/kXrnBXUv2uEvImpORd5AnKFv6oU71", - "gDGgwbhuDHu7neu0RJgNtcqnMyNgezu967kRKp01+t+u160jX715PRtG9eP9UITeTft6fuSGf7y2bhv4", - "JhrYs6F0BPk6WPceaZbtu1+pCtKbYWe3GgBFY9iMh/3VzKd9jbD5QDTNeytCcCFQiruOk30dqlCqhT4z", - "R4QvCIXkLvk3AAD//w==", + "3FpNb+M2E/4rAt/3VMiWne1JPQXbbZuim6R1gC0Q5MBI44hbSeSSdDaB4f9ekJQsiZL1YUv56C2xhjPP", + "POQzFIfaooAmjKaQSoH8LeIgGE0F6H9WJGEx/JX9pH4JaCohlepPCU/SYzEmqfpPBBEkWP/+zAD5SEhO", + "0ge02+1cFIIIOGGS0BT56NwR2q+Tx3Lo/VcIJFKmxo+O/pEqq6cr89DfIsYpAy6JAXcRlqKRVMIDcLRz", + "0YU4DxMDKnt4T2kMOFUPC2f/57BGPvqfV+TvZcG9qwIPh28bwiFE/m0+2FWhizh3FbdVjGvChbzECTQQ", + "4yJO46YHVlRt5ZZc3WlOSbqmanBMAsgmJ9WB0OeLG+VdEqncoxsQ0lkBfwSOXPQIXJhpWM4X84UypAxS", + "zAjy0Yf5Yr5ELmJYRhq/l823yc/bMsxxslNPHkCnq5LFal7VbKBfQX4sD9CuOE5AAhfIv62sH8xYTAI9", + "2PsqqLWK2qanujAyNpCvYSM3p0FHRmUuJd/A7s6trvGzxeJQvL2dZwlhp2N6AaX/EGhnQ1vUaKgKgnGS", + "EEkelSE8sZiGgPw1jgVkiQW5mzw15JaoWlOeYGlE8OEMuTVN7NxeERU9BwLCyRGzKKGDOcfPfcPiSlgi", + "IRG94u9/MdEa8NRgtPE9HYw9LTQXTC9eaAVQv1Jmh65HbKPguIhTyb2aSWAMCg4bMwgoqpOgnjlCYi5J", + "+uB8JzJy0k1yr0tlo5elqBBhl267uoSwxptYHlthIN2YpdZYYD6lm+RaFRbRVWGu84cmReXWecTxBkSe", + "57cN8OfSCtOuZXSdFdEiY/UE+bfLxcI9Wyzu3B7FoF5yfzTcVGaCOvlqyZKPAIfA28rrb8bi1PIa5W6y", + "5P+eXZeGTFpoW0LPPmW14UVKbx3IubJuBvFihfgAqlcux3VUpjY1kzVFdT6E4N0V6XoimaM8IQvg0YeO", + "lKaz31dXl3mRcZ17uklDBwtHRuBw/N0xWJzMx2GBYiFmNxGnm4fomB3F9ricrTLr2Rcio9llbv1iu0yM", + "7yHO1q7Wl7ed64r6Q+ur/h/2sHohblJPn7f0cfTtIiGf9RlIZ4jGfPcvc5afjoaSduiQNAZrfcT/Uvzs", + "t7ThFJU34glY6rGkJqbokjYJr5uf6rgWdsrbxn9Ievv8q+IbQFyn+k5h7k3Ir6a7bnb66O0UXl5VcAmW", + "nDxZeiNhezX6XBt0TCki4eRCM9lNR9heaIMYO36P66BsmMKmJqcktZ8G8XPSBtdB0QCxTcZPbX8jYQ9y", + "Rtjd3rPi6pvbMNZO2Nreh+qqcutBzWn72pvWGcNCZMfRPhc014V56/XMgJP2q1y+6IblzwCsuHs7lHLJ", + "qqNVGAKw9t6P1ScNjeujNWO1TYqFEhaYxz7uZ8zFShEQthH3Z9WygzzBcABOmJs7rZ09i0cx1hVLwaCG", + "U4Bv6M0SdixcNj5chaaEdmyl/EJ50jnV2qhjlnt1k+3bhPHpUkPRwG6yherFQPXrKtucTX/HZ0UcI+A+", + "1a6LDzvbaa602yQ8WkCrY2zHab8wfOX+uwX2uDtSy8nAK9ITKpv5jqh6wOjRYFzVhr3dzrVJEU3GWuXL", + "ngG0vZ3e9dQMlc4a3W/Xq8aRr968nowj+3jfl6F3076enrn+39atmga+iQb2ZCwdIb4W1b1HmWX77hci", + "I3Mz7G2XPaioDZvwsL+c+LSvGNbfrxrcGx4jH0VSMt/zso9XJQg5V2fmBLM5Jmh3t/s3AAD//w==", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/internal/test/parameters/roundtrip/chi/gen/types.gen.go b/internal/test/parameters/roundtrip/chi/gen/types.gen.go index cf9e95942..d0ea47a20 100644 --- a/internal/test/parameters/roundtrip/chi/gen/types.gen.go +++ b/internal/test/parameters/roundtrip/chi/gen/types.gen.go @@ -93,6 +93,9 @@ type GetHeaderParams struct { // XComplexObject complex object XComplexObject *ComplexObject `json:"X-Complex-Object,omitempty"` + // XPassThrough non-JSON content, bound as the raw header string + XPassThrough *string `json:"X-Pass-Through,omitempty"` + // N1StartingWithNumber name starting with number N1StartingWithNumber *string `json:"1-Starting-With-Number,omitempty"` } diff --git a/internal/test/parameters/roundtrip/client/gen/client.gen.go b/internal/test/parameters/roundtrip/client/gen/client.gen.go index 77de438c5..4db51cf2c 100644 --- a/internal/test/parameters/roundtrip/client/gen/client.gen.go +++ b/internal/test/parameters/roundtrip/client/gen/client.gen.go @@ -105,6 +105,9 @@ type GetHeaderParams struct { // XComplexObject complex object XComplexObject *ComplexObject `json:"X-Complex-Object,omitempty"` + // XPassThrough non-JSON content, bound as the raw header string + XPassThrough *string `json:"X-Pass-Through,omitempty"` + // N1StartingWithNumber name starting with number N1StartingWithNumber *string `json:"1-Starting-With-Number,omitempty"` } @@ -1007,15 +1010,23 @@ func NewGetHeaderRequest(server string, params *GetHeaderParams) (*http.Request, req.Header.Set("X-Complex-Object", headerParam6) } - if params.N1StartingWithNumber != nil { + if params.XPassThrough != nil { var headerParam7 string - headerParam7, err = runtime.StyleParamWithOptions("simple", false, "1-Starting-With-Number", *params.N1StartingWithNumber, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationHeader, Type: "string", Format: ""}) + headerParam7 = *params.XPassThrough + + req.Header.Set("X-Pass-Through", headerParam7) + } + + if params.N1StartingWithNumber != nil { + var headerParam8 string + + headerParam8, err = runtime.StyleParamWithOptions("simple", false, "1-Starting-With-Number", *params.N1StartingWithNumber, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationHeader, Type: "string", Format: ""}) if err != nil { return nil, err } - req.Header.Set("1-Starting-With-Number", headerParam7) + req.Header.Set("1-Starting-With-Number", headerParam8) } } diff --git a/internal/test/parameters/roundtrip/echo/gen/server.gen.go b/internal/test/parameters/roundtrip/echo/gen/server.gen.go index f55c13815..54e8ffbe9 100644 --- a/internal/test/parameters/roundtrip/echo/gen/server.gen.go +++ b/internal/test/parameters/roundtrip/echo/gen/server.gen.go @@ -361,6 +361,18 @@ func (w *ServerInterfaceWrapper) GetHeader(ctx echo.Context) error { params.XComplexObject = &XComplexObject } + // ------------- Optional header parameter "X-Pass-Through" ------------- + if valueList, found := headers[http.CanonicalHeaderKey("X-Pass-Through")]; found { + var XPassThrough string + n := len(valueList) + if n != 1 { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Expected one value for X-Pass-Through, got %d", n)) + } + + XPassThrough = valueList[0] + + params.XPassThrough = &XPassThrough + } // ------------- Optional header parameter "1-Starting-With-Number" ------------- if valueList, found := headers[http.CanonicalHeaderKey("1-Starting-With-Number")]; found { var N1StartingWithNumber string @@ -901,28 +913,28 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "3FpLb+M2F/0rwv2+VaFYdqYrdRVMp22ATiatA0yBIAtGuo44lUQOSacJDP33gpRkPa2HLeXRXWJd3sch", - "z6F4qR14LOIsxlhJcHcgUHIWSzT/rGnEQ/wz+0n/4rFYYaz0nwqflMNDQmP9n/QCjIj5/ZkjuCCVoPED", - "JElig4/SE5QrymJw4cKSxq+Vx7LY/Tf0FGjT1I+J/pFpq6cv6UN3B1wwjkLRNLlLvxSNxgofUEBiw6W8", - "8KM0qezhPWMhklg/LJz9X+AGXPifU9TvZMGdL0U+Ar9vqUAf3Nt8sK1DF3HuKm6rOW6okOqKRNgCjA2C", - "hW0PalGNlV1ydWcwpfGG6cEh9TCbnNgEgs+XN9q7okq7hxuUylqjeEQBNjyikOk0rBbLxVIbMo4x4RRc", - "+LBYLlZgAycqMPk72Xyn9Tk7TgSJEv3kAU25ulii51XPBvyK6mN5gHElSIQKhQT3trJ+COch9cxg55tk", - "tVXUNT3VhZGhAa5JG+wcBhMZylgqscXkzq6u8fPl8lC8vZ1TI0JiYjoeY39T7EbDWDRgqBKCCxpRRR+1", - "IT7xkPkI7oaEErPCvNxNXhrYJag2TEREpST4cA52gxOJPSiihudAQDw5YhbFt4gQ5HloWFIJSxVGclD8", - "/S9ptJZ8Gml04T1fGntYWE6YQbiwSkLDpKweuhmxC4LjIs5F92olXmpQYNhagcegCYJ+ZklFhKLxg/UP", - "VYEVb6N7I5WtXlayAkRduuvq4uOGbEN1rMJgvE2XWqvAfIq30bUWFtmnMNf5w7RE7dZ6JOEWZV7n9y2K", - "59IKM65VcJ2JaFGxfgLu7Wq5tM+Xyzt7gBg0JffHFJvKTDArXy1Z8QESH0WXvP6WWpwqr0HuJiv+r7Pr", - "0pBZhbYj9NmnTBteRHqbiVxo6/YkXkyID2T1ynLczCrVpnaw5lDnQxm8O5FuFpI5ygs6QrLrPldn68z6", - "7CtVwdlVbv1iMh6SewyzxWEWsLNbGMn6ofNd+vf6sKbStS3PIa/B0xDIBqmezSHDVAhTvlyXMcuPH2NB", - "O3QKmQK1Iex6KXz2e8Z4iMo73QwoDVhSM0N0xdqI149PdVwHOmVd/g9Rb19/lXwjgOtl3ynIvQn6NXjX", - "j84Qvp2Cy6sSLiJK0Kca36jfrUafG4OOkSLqz060tLr5ANsTbRRix+9xPZCNY9jc4JSo9tMofE7a4Hog", - "GkG22fBp7G/UHwDOBLvbe2Zcc3Mbh9oJW9v7YF2VbgOgOW1fe9M840TKm0Cw7UMw5AbkujDvvP8YcX/2", - "KrcbpiP4MyIvLrcOlVyy6unF+Yi8u7lSa0T6qeujOVPrSxQLxS9ynvq4nyEXakag3wXcH1XLHvAkJx5a", - "fm5udbbOajjKqe4wCgRNOkXyLc1Pyo9Nl0+frs6mlO3UTPmFiah3qo1RzywPatfW2/XTw6WHwsh2bS2r", - "F0tqWNu2jtn8l2i1iFME3Jfad7NQr3aeO+MuCk8W0Mr2wgNxum/kXrnBXUv2uEvImpORd5AnKFv6oU71", - "gDGgwbhuDHu7neu0RJgNtcqnMyNgezu967kRKp01+t+u160jX715PRtG9eP9UITeTft6fuSGf7y2bhv4", - "JhrYs6F0BPk6WPceaZbtu1+pCtKbYWe3GgBFY9iMh/3VzKd9jbD5QDTNeytCcCFQiruOk30dqlCqhT4z", - "R4QvCIXkLvk3AAD//w==", + "3FpNb+M2E/4rAt/3VMiWne1JPQXbbZuim6R1gC0Q5MBI44hbSeSSdDaB4f9ekJQsiZL1YUv56C2xhjPP", + "POQzFIfaooAmjKaQSoH8LeIgGE0F6H9WJGEx/JX9pH4JaCohlepPCU/SYzEmqfpPBBEkWP/+zAD5SEhO", + "0ge02+1cFIIIOGGS0BT56NwR2q+Tx3Lo/VcIJFKmxo+O/pEqq6cr89DfIsYpAy6JAXcRlqKRVMIDcLRz", + "0YU4DxMDKnt4T2kMOFUPC2f/57BGPvqfV+TvZcG9qwIPh28bwiFE/m0+2FWhizh3FbdVjGvChbzECTQQ", + "4yJO46YHVlRt5ZZc3WlOSbqmanBMAsgmJ9WB0OeLG+VdEqncoxsQ0lkBfwSOXPQIXJhpWM4X84UypAxS", + "zAjy0Yf5Yr5ELmJYRhq/l823yc/bMsxxslNPHkCnq5LFal7VbKBfQX4sD9CuOE5AAhfIv62sH8xYTAI9", + "2PsqqLWK2qanujAyNpCvYSM3p0FHRmUuJd/A7s6trvGzxeJQvL2dZwlhp2N6AaX/EGhnQ1vUaKgKgnGS", + "EEkelSE8sZiGgPw1jgVkiQW5mzw15JaoWlOeYGlE8OEMuTVN7NxeERU9BwLCyRGzKKGDOcfPfcPiSlgi", + "IRG94u9/MdEa8NRgtPE9HYw9LTQXTC9eaAVQv1Jmh65HbKPguIhTyb2aSWAMCg4bMwgoqpOgnjlCYi5J", + "+uB8JzJy0k1yr0tlo5elqBBhl267uoSwxptYHlthIN2YpdZYYD6lm+RaFRbRVWGu84cmReXWecTxBkSe", + "57cN8OfSCtOuZXSdFdEiY/UE+bfLxcI9Wyzu3B7FoF5yfzTcVGaCOvlqyZKPAIfA28rrb8bi1PIa5W6y", + "5P+eXZeGTFpoW0LPPmW14UVKbx3IubJuBvFihfgAqlcux3VUpjY1kzVFdT6E4N0V6XoimaM8IQvg0YeO", + "lKaz31dXl3mRcZ17uklDBwtHRuBw/N0xWJzMx2GBYiFmNxGnm4fomB3F9ricrTLr2Rcio9llbv1iu0yM", + "7yHO1q7Wl7ed64r6Q+ur/h/2sHohblJPn7f0cfTtIiGf9RlIZ4jGfPcvc5afjoaSduiQNAZrfcT/Uvzs", + "t7ThFJU34glY6rGkJqbokjYJr5uf6rgWdsrbxn9Ievv8q+IbQFyn+k5h7k3Ir6a7bnb66O0UXl5VcAmW", + "nDxZeiNhezX6XBt0TCki4eRCM9lNR9heaIMYO36P66BsmMKmJqcktZ8G8XPSBtdB0QCxTcZPbX8jYQ9y", + "Rtjd3rPi6pvbMNZO2Nreh+qqcutBzWn72pvWGcNCZMfRPhc014V56/XMgJP2q1y+6IblzwCsuHs7lHLJ", + "qqNVGAKw9t6P1ScNjeujNWO1TYqFEhaYxz7uZ8zFShEQthH3Z9WygzzBcABOmJs7rZ09i0cx1hVLwaCG", + "U4Bv6M0SdixcNj5chaaEdmyl/EJ50jnV2qhjlnt1k+3bhPHpUkPRwG6yherFQPXrKtucTX/HZ0UcI+A+", + "1a6LDzvbaa602yQ8WkCrY2zHab8wfOX+uwX2uDtSy8nAK9ITKpv5jqh6wOjRYFzVhr3dzrVJEU3GWuXL", + "ngG0vZ3e9dQMlc4a3W/Xq8aRr968nowj+3jfl6F3076enrn+39atmga+iQb2ZCwdIb4W1b1HmWX77hci", + "I3Mz7G2XPaioDZvwsL+c+LSvGNbfrxrcGx4jH0VSMt/zso9XJQg5V2fmBLM5Jmh3t/s3AAD//w==", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/internal/test/parameters/roundtrip/echo/gen/types.gen.go b/internal/test/parameters/roundtrip/echo/gen/types.gen.go index 043be6dba..2a902d51c 100644 --- a/internal/test/parameters/roundtrip/echo/gen/types.gen.go +++ b/internal/test/parameters/roundtrip/echo/gen/types.gen.go @@ -93,6 +93,9 @@ type GetHeaderParams struct { // XComplexObject complex object XComplexObject *ComplexObject `json:"X-Complex-Object,omitempty"` + // XPassThrough non-JSON content, bound as the raw header string + XPassThrough *string `json:"X-Pass-Through,omitempty"` + // N1StartingWithNumber name starting with number N1StartingWithNumber *string `json:"1-Starting-With-Number,omitempty"` } diff --git a/internal/test/parameters/roundtrip/echov5/gen/server.gen.go b/internal/test/parameters/roundtrip/echov5/gen/server.gen.go index 30bebc6b4..dd0d3a30f 100644 --- a/internal/test/parameters/roundtrip/echov5/gen/server.gen.go +++ b/internal/test/parameters/roundtrip/echov5/gen/server.gen.go @@ -361,6 +361,18 @@ func (w *ServerInterfaceWrapper) GetHeader(ctx *echo.Context) error { params.XComplexObject = &XComplexObject } + // ------------- Optional header parameter "X-Pass-Through" ------------- + if valueList, found := headers[http.CanonicalHeaderKey("X-Pass-Through")]; found { + var XPassThrough string + n := len(valueList) + if n != 1 { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Expected one value for X-Pass-Through, got %d", n)) + } + + XPassThrough = valueList[0] + + params.XPassThrough = &XPassThrough + } // ------------- Optional header parameter "1-Starting-With-Number" ------------- if valueList, found := headers[http.CanonicalHeaderKey("1-Starting-With-Number")]; found { var N1StartingWithNumber string @@ -901,28 +913,28 @@ func RegisterHandlersWithOptions(router EchoRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "3FpLb+M2F/0rwv2+VaFYdqYrdRVMp22ATiatA0yBIAtGuo44lUQOSacJDP33gpRkPa2HLeXRXWJd3sch", - "z6F4qR14LOIsxlhJcHcgUHIWSzT/rGnEQ/wz+0n/4rFYYaz0nwqflMNDQmP9n/QCjIj5/ZkjuCCVoPED", - "JElig4/SE5QrymJw4cKSxq+Vx7LY/Tf0FGjT1I+J/pFpq6cv6UN3B1wwjkLRNLlLvxSNxgofUEBiw6W8", - "8KM0qezhPWMhklg/LJz9X+AGXPifU9TvZMGdL0U+Ar9vqUAf3Nt8sK1DF3HuKm6rOW6okOqKRNgCjA2C", - "hW0PalGNlV1ydWcwpfGG6cEh9TCbnNgEgs+XN9q7okq7hxuUylqjeEQBNjyikOk0rBbLxVIbMo4x4RRc", - "+LBYLlZgAycqMPk72Xyn9Tk7TgSJEv3kAU25ulii51XPBvyK6mN5gHElSIQKhQT3trJ+COch9cxg55tk", - "tVXUNT3VhZGhAa5JG+wcBhMZylgqscXkzq6u8fPl8lC8vZ1TI0JiYjoeY39T7EbDWDRgqBKCCxpRRR+1", - "IT7xkPkI7oaEErPCvNxNXhrYJag2TEREpST4cA52gxOJPSiihudAQDw5YhbFt4gQ5HloWFIJSxVGclD8", - "/S9ptJZ8Gml04T1fGntYWE6YQbiwSkLDpKweuhmxC4LjIs5F92olXmpQYNhagcegCYJ+ZklFhKLxg/UP", - "VYEVb6N7I5WtXlayAkRduuvq4uOGbEN1rMJgvE2XWqvAfIq30bUWFtmnMNf5w7RE7dZ6JOEWZV7n9y2K", - "59IKM65VcJ2JaFGxfgLu7Wq5tM+Xyzt7gBg0JffHFJvKTDArXy1Z8QESH0WXvP6WWpwqr0HuJiv+r7Pr", - "0pBZhbYj9NmnTBteRHqbiVxo6/YkXkyID2T1ynLczCrVpnaw5lDnQxm8O5FuFpI5ygs6QrLrPldn68z6", - "7CtVwdlVbv1iMh6SewyzxWEWsLNbGMn6ofNd+vf6sKbStS3PIa/B0xDIBqmezSHDVAhTvlyXMcuPH2NB", - "O3QKmQK1Iex6KXz2e8Z4iMo73QwoDVhSM0N0xdqI149PdVwHOmVd/g9Rb19/lXwjgOtl3ynIvQn6NXjX", - "j84Qvp2Cy6sSLiJK0Kca36jfrUafG4OOkSLqz060tLr5ANsTbRRix+9xPZCNY9jc4JSo9tMofE7a4Hog", - "GkG22fBp7G/UHwDOBLvbe2Zcc3Mbh9oJW9v7YF2VbgOgOW1fe9M840TKm0Cw7UMw5AbkujDvvP8YcX/2", - "KrcbpiP4MyIvLrcOlVyy6unF+Yi8u7lSa0T6qeujOVPrSxQLxS9ynvq4nyEXakag3wXcH1XLHvAkJx5a", - "fm5udbbOajjKqe4wCgRNOkXyLc1Pyo9Nl0+frs6mlO3UTPmFiah3qo1RzywPatfW2/XTw6WHwsh2bS2r", - "F0tqWNu2jtn8l2i1iFME3Jfad7NQr3aeO+MuCk8W0Mr2wgNxum/kXrnBXUv2uEvImpORd5AnKFv6oU71", - "gDGgwbhuDHu7neu0RJgNtcqnMyNgezu967kRKp01+t+u160jX715PRtG9eP9UITeTft6fuSGf7y2bhv4", - "JhrYs6F0BPk6WPceaZbtu1+pCtKbYWe3GgBFY9iMh/3VzKd9jbD5QDTNeytCcCFQiruOk30dqlCqhT4z", - "R4QvCIXkLvk3AAD//w==", + "3FpNb+M2E/4rAt/3VMiWne1JPQXbbZuim6R1gC0Q5MBI44hbSeSSdDaB4f9ekJQsiZL1YUv56C2xhjPP", + "POQzFIfaooAmjKaQSoH8LeIgGE0F6H9WJGEx/JX9pH4JaCohlepPCU/SYzEmqfpPBBEkWP/+zAD5SEhO", + "0ge02+1cFIIIOGGS0BT56NwR2q+Tx3Lo/VcIJFKmxo+O/pEqq6cr89DfIsYpAy6JAXcRlqKRVMIDcLRz", + "0YU4DxMDKnt4T2kMOFUPC2f/57BGPvqfV+TvZcG9qwIPh28bwiFE/m0+2FWhizh3FbdVjGvChbzECTQQ", + "4yJO46YHVlRt5ZZc3WlOSbqmanBMAsgmJ9WB0OeLG+VdEqncoxsQ0lkBfwSOXPQIXJhpWM4X84UypAxS", + "zAjy0Yf5Yr5ELmJYRhq/l823yc/bMsxxslNPHkCnq5LFal7VbKBfQX4sD9CuOE5AAhfIv62sH8xYTAI9", + "2PsqqLWK2qanujAyNpCvYSM3p0FHRmUuJd/A7s6trvGzxeJQvL2dZwlhp2N6AaX/EGhnQ1vUaKgKgnGS", + "EEkelSE8sZiGgPw1jgVkiQW5mzw15JaoWlOeYGlE8OEMuTVN7NxeERU9BwLCyRGzKKGDOcfPfcPiSlgi", + "IRG94u9/MdEa8NRgtPE9HYw9LTQXTC9eaAVQv1Jmh65HbKPguIhTyb2aSWAMCg4bMwgoqpOgnjlCYi5J", + "+uB8JzJy0k1yr0tlo5elqBBhl267uoSwxptYHlthIN2YpdZYYD6lm+RaFRbRVWGu84cmReXWecTxBkSe", + "57cN8OfSCtOuZXSdFdEiY/UE+bfLxcI9Wyzu3B7FoF5yfzTcVGaCOvlqyZKPAIfA28rrb8bi1PIa5W6y", + "5P+eXZeGTFpoW0LPPmW14UVKbx3IubJuBvFihfgAqlcux3VUpjY1kzVFdT6E4N0V6XoimaM8IQvg0YeO", + "lKaz31dXl3mRcZ17uklDBwtHRuBw/N0xWJzMx2GBYiFmNxGnm4fomB3F9ricrTLr2Rcio9llbv1iu0yM", + "7yHO1q7Wl7ed64r6Q+ur/h/2sHohblJPn7f0cfTtIiGf9RlIZ4jGfPcvc5afjoaSduiQNAZrfcT/Uvzs", + "t7ThFJU34glY6rGkJqbokjYJr5uf6rgWdsrbxn9Ievv8q+IbQFyn+k5h7k3Ir6a7bnb66O0UXl5VcAmW", + "nDxZeiNhezX6XBt0TCki4eRCM9lNR9heaIMYO36P66BsmMKmJqcktZ8G8XPSBtdB0QCxTcZPbX8jYQ9y", + "Rtjd3rPi6pvbMNZO2Nreh+qqcutBzWn72pvWGcNCZMfRPhc014V56/XMgJP2q1y+6IblzwCsuHs7lHLJ", + "qqNVGAKw9t6P1ScNjeujNWO1TYqFEhaYxz7uZ8zFShEQthH3Z9WygzzBcABOmJs7rZ09i0cx1hVLwaCG", + "U4Bv6M0SdixcNj5chaaEdmyl/EJ50jnV2qhjlnt1k+3bhPHpUkPRwG6yherFQPXrKtucTX/HZ0UcI+A+", + "1a6LDzvbaa602yQ8WkCrY2zHab8wfOX+uwX2uDtSy8nAK9ITKpv5jqh6wOjRYFzVhr3dzrVJEU3GWuXL", + "ngG0vZ3e9dQMlc4a3W/Xq8aRr968nowj+3jfl6F3076enrn+39atmga+iQb2ZCwdIb4W1b1HmWX77hci", + "I3Mz7G2XPaioDZvwsL+c+LSvGNbfrxrcGx4jH0VSMt/zso9XJQg5V2fmBLM5Jmh3t/s3AAD//w==", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/internal/test/parameters/roundtrip/echov5/gen/types.gen.go b/internal/test/parameters/roundtrip/echov5/gen/types.gen.go index f9ac88c94..2ff655c92 100644 --- a/internal/test/parameters/roundtrip/echov5/gen/types.gen.go +++ b/internal/test/parameters/roundtrip/echov5/gen/types.gen.go @@ -93,6 +93,9 @@ type GetHeaderParams struct { // XComplexObject complex object XComplexObject *ComplexObject `json:"X-Complex-Object,omitempty"` + // XPassThrough non-JSON content, bound as the raw header string + XPassThrough *string `json:"X-Pass-Through,omitempty"` + // N1StartingWithNumber name starting with number N1StartingWithNumber *string `json:"1-Starting-With-Number,omitempty"` } diff --git a/internal/test/parameters/roundtrip/fiber/gen/server.gen.go b/internal/test/parameters/roundtrip/fiber/gen/server.gen.go index 0557bc8fa..71a6febb8 100644 --- a/internal/test/parameters/roundtrip/fiber/gen/server.gen.go +++ b/internal/test/parameters/roundtrip/fiber/gen/server.gen.go @@ -458,6 +458,20 @@ func (siw *ServerInterfaceWrapper) GetHeader(c *fiber.Ctx) error { } + // ------------- Optional header parameter "X-Pass-Through" ------------- + if valueList, found := headers[http.CanonicalHeaderKey("X-Pass-Through")]; found { + var XPassThrough string + n := len(valueList) + if n != 1 { + return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Too many values for ParamName X-Pass-Through, 1 is required, but %d found", n)) + } + + XPassThrough = valueList[0] + + params.XPassThrough = &XPassThrough + + } + // ------------- Optional header parameter "1-Starting-With-Number" ------------- if valueList, found := headers[http.CanonicalHeaderKey("1-Starting-With-Number")]; found { var N1StartingWithNumber string @@ -1335,28 +1349,28 @@ func RegisterHandlersWithOptions(router fiber.Router, si ServerInterface, option // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "3FpLb+M2F/0rwv2+VaFYdqYrdRVMp22ATiatA0yBIAtGuo44lUQOSacJDP33gpRkPa2HLeXRXWJd3sch", - "z6F4qR14LOIsxlhJcHcgUHIWSzT/rGnEQ/wz+0n/4rFYYaz0nwqflMNDQmP9n/QCjIj5/ZkjuCCVoPED", - "JElig4/SE5QrymJw4cKSxq+Vx7LY/Tf0FGjT1I+J/pFpq6cv6UN3B1wwjkLRNLlLvxSNxgofUEBiw6W8", - "8KM0qezhPWMhklg/LJz9X+AGXPifU9TvZMGdL0U+Ar9vqUAf3Nt8sK1DF3HuKm6rOW6okOqKRNgCjA2C", - "hW0PalGNlV1ydWcwpfGG6cEh9TCbnNgEgs+XN9q7okq7hxuUylqjeEQBNjyikOk0rBbLxVIbMo4x4RRc", - "+LBYLlZgAycqMPk72Xyn9Tk7TgSJEv3kAU25ulii51XPBvyK6mN5gHElSIQKhQT3trJ+COch9cxg55tk", - "tVXUNT3VhZGhAa5JG+wcBhMZylgqscXkzq6u8fPl8lC8vZ1TI0JiYjoeY39T7EbDWDRgqBKCCxpRRR+1", - "IT7xkPkI7oaEErPCvNxNXhrYJag2TEREpST4cA52gxOJPSiihudAQDw5YhbFt4gQ5HloWFIJSxVGclD8", - "/S9ptJZ8Gml04T1fGntYWE6YQbiwSkLDpKweuhmxC4LjIs5F92olXmpQYNhagcegCYJ+ZklFhKLxg/UP", - "VYEVb6N7I5WtXlayAkRduuvq4uOGbEN1rMJgvE2XWqvAfIq30bUWFtmnMNf5w7RE7dZ6JOEWZV7n9y2K", - "59IKM65VcJ2JaFGxfgLu7Wq5tM+Xyzt7gBg0JffHFJvKTDArXy1Z8QESH0WXvP6WWpwqr0HuJiv+r7Pr", - "0pBZhbYj9NmnTBteRHqbiVxo6/YkXkyID2T1ynLczCrVpnaw5lDnQxm8O5FuFpI5ygs6QrLrPldn68z6", - "7CtVwdlVbv1iMh6SewyzxWEWsLNbGMn6ofNd+vf6sKbStS3PIa/B0xDIBqmezSHDVAhTvlyXMcuPH2NB", - "O3QKmQK1Iex6KXz2e8Z4iMo73QwoDVhSM0N0xdqI149PdVwHOmVd/g9Rb19/lXwjgOtl3ynIvQn6NXjX", - "j84Qvp2Cy6sSLiJK0Kca36jfrUafG4OOkSLqz060tLr5ANsTbRRix+9xPZCNY9jc4JSo9tMofE7a4Hog", - "GkG22fBp7G/UHwDOBLvbe2Zcc3Mbh9oJW9v7YF2VbgOgOW1fe9M840TKm0Cw7UMw5AbkujDvvP8YcX/2", - "KrcbpiP4MyIvLrcOlVyy6unF+Yi8u7lSa0T6qeujOVPrSxQLxS9ynvq4nyEXakag3wXcH1XLHvAkJx5a", - "fm5udbbOajjKqe4wCgRNOkXyLc1Pyo9Nl0+frs6mlO3UTPmFiah3qo1RzywPatfW2/XTw6WHwsh2bS2r", - "F0tqWNu2jtn8l2i1iFME3Jfad7NQr3aeO+MuCk8W0Mr2wgNxum/kXrnBXUv2uEvImpORd5AnKFv6oU71", - "gDGgwbhuDHu7neu0RJgNtcqnMyNgezu967kRKp01+t+u160jX715PRtG9eP9UITeTft6fuSGf7y2bhv4", - "JhrYs6F0BPk6WPceaZbtu1+pCtKbYWe3GgBFY9iMh/3VzKd9jbD5QDTNeytCcCFQiruOk30dqlCqhT4z", - "R4QvCIXkLvk3AAD//w==", + "3FpNb+M2E/4rAt/3VMiWne1JPQXbbZuim6R1gC0Q5MBI44hbSeSSdDaB4f9ekJQsiZL1YUv56C2xhjPP", + "POQzFIfaooAmjKaQSoH8LeIgGE0F6H9WJGEx/JX9pH4JaCohlepPCU/SYzEmqfpPBBEkWP/+zAD5SEhO", + "0ge02+1cFIIIOGGS0BT56NwR2q+Tx3Lo/VcIJFKmxo+O/pEqq6cr89DfIsYpAy6JAXcRlqKRVMIDcLRz", + "0YU4DxMDKnt4T2kMOFUPC2f/57BGPvqfV+TvZcG9qwIPh28bwiFE/m0+2FWhizh3FbdVjGvChbzECTQQ", + "4yJO46YHVlRt5ZZc3WlOSbqmanBMAsgmJ9WB0OeLG+VdEqncoxsQ0lkBfwSOXPQIXJhpWM4X84UypAxS", + "zAjy0Yf5Yr5ELmJYRhq/l823yc/bMsxxslNPHkCnq5LFal7VbKBfQX4sD9CuOE5AAhfIv62sH8xYTAI9", + "2PsqqLWK2qanujAyNpCvYSM3p0FHRmUuJd/A7s6trvGzxeJQvL2dZwlhp2N6AaX/EGhnQ1vUaKgKgnGS", + "EEkelSE8sZiGgPw1jgVkiQW5mzw15JaoWlOeYGlE8OEMuTVN7NxeERU9BwLCyRGzKKGDOcfPfcPiSlgi", + "IRG94u9/MdEa8NRgtPE9HYw9LTQXTC9eaAVQv1Jmh65HbKPguIhTyb2aSWAMCg4bMwgoqpOgnjlCYi5J", + "+uB8JzJy0k1yr0tlo5elqBBhl267uoSwxptYHlthIN2YpdZYYD6lm+RaFRbRVWGu84cmReXWecTxBkSe", + "57cN8OfSCtOuZXSdFdEiY/UE+bfLxcI9Wyzu3B7FoF5yfzTcVGaCOvlqyZKPAIfA28rrb8bi1PIa5W6y", + "5P+eXZeGTFpoW0LPPmW14UVKbx3IubJuBvFihfgAqlcux3VUpjY1kzVFdT6E4N0V6XoimaM8IQvg0YeO", + "lKaz31dXl3mRcZ17uklDBwtHRuBw/N0xWJzMx2GBYiFmNxGnm4fomB3F9ricrTLr2Rcio9llbv1iu0yM", + "7yHO1q7Wl7ed64r6Q+ur/h/2sHohblJPn7f0cfTtIiGf9RlIZ4jGfPcvc5afjoaSduiQNAZrfcT/Uvzs", + "t7ThFJU34glY6rGkJqbokjYJr5uf6rgWdsrbxn9Ievv8q+IbQFyn+k5h7k3Ir6a7bnb66O0UXl5VcAmW", + "nDxZeiNhezX6XBt0TCki4eRCM9lNR9heaIMYO36P66BsmMKmJqcktZ8G8XPSBtdB0QCxTcZPbX8jYQ9y", + "Rtjd3rPi6pvbMNZO2Nreh+qqcutBzWn72pvWGcNCZMfRPhc014V56/XMgJP2q1y+6IblzwCsuHs7lHLJ", + "qqNVGAKw9t6P1ScNjeujNWO1TYqFEhaYxz7uZ8zFShEQthH3Z9WygzzBcABOmJs7rZ09i0cx1hVLwaCG", + "U4Bv6M0SdixcNj5chaaEdmyl/EJ50jnV2qhjlnt1k+3bhPHpUkPRwG6yherFQPXrKtucTX/HZ0UcI+A+", + "1a6LDzvbaa602yQ8WkCrY2zHab8wfOX+uwX2uDtSy8nAK9ITKpv5jqh6wOjRYFzVhr3dzrVJEU3GWuXL", + "ngG0vZ3e9dQMlc4a3W/Xq8aRr968nowj+3jfl6F3076enrn+39atmga+iQb2ZCwdIb4W1b1HmWX77hci", + "I3Mz7G2XPaioDZvwsL+c+LSvGNbfrxrcGx4jH0VSMt/zso9XJQg5V2fmBLM5Jmh3t/s3AAD//w==", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/internal/test/parameters/roundtrip/fiber/gen/types.gen.go b/internal/test/parameters/roundtrip/fiber/gen/types.gen.go index c7b09599f..64f4da202 100644 --- a/internal/test/parameters/roundtrip/fiber/gen/types.gen.go +++ b/internal/test/parameters/roundtrip/fiber/gen/types.gen.go @@ -93,6 +93,9 @@ type GetHeaderParams struct { // XComplexObject complex object XComplexObject *ComplexObject `json:"X-Complex-Object,omitempty"` + // XPassThrough non-JSON content, bound as the raw header string + XPassThrough *string `json:"X-Pass-Through,omitempty"` + // N1StartingWithNumber name starting with number N1StartingWithNumber *string `json:"1-Starting-With-Number,omitempty"` } diff --git a/internal/test/parameters/roundtrip/gin/gen/server.gen.go b/internal/test/parameters/roundtrip/gin/gen/server.gen.go index 5bf8e4232..1168b7205 100644 --- a/internal/test/parameters/roundtrip/gin/gen/server.gen.go +++ b/internal/test/parameters/roundtrip/gin/gen/server.gen.go @@ -456,6 +456,21 @@ func (siw *ServerInterfaceWrapper) GetHeader(c *gin.Context) { } + // ------------- Optional header parameter "X-Pass-Through" ------------- + if valueList, found := headers[http.CanonicalHeaderKey("X-Pass-Through")]; found { + var XPassThrough string + n := len(valueList) + if n != 1 { + siw.ErrorHandler(c, fmt.Errorf("Expected one value for X-Pass-Through, got %d", n), http.StatusBadRequest) + return + } + + XPassThrough = valueList[0] + + params.XPassThrough = &XPassThrough + + } + // ------------- Optional header parameter "1-Starting-With-Number" ------------- if valueList, found := headers[http.CanonicalHeaderKey("1-Starting-With-Number")]; found { var N1StartingWithNumber string @@ -1198,28 +1213,28 @@ func RegisterHandlersWithOptions(router gin.IRouter, si ServerInterface, options // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "3FpLb+M2F/0rwv2+VaFYdqYrdRVMp22ATiatA0yBIAtGuo44lUQOSacJDP33gpRkPa2HLeXRXWJd3sch", - "z6F4qR14LOIsxlhJcHcgUHIWSzT/rGnEQ/wz+0n/4rFYYaz0nwqflMNDQmP9n/QCjIj5/ZkjuCCVoPED", - "JElig4/SE5QrymJw4cKSxq+Vx7LY/Tf0FGjT1I+J/pFpq6cv6UN3B1wwjkLRNLlLvxSNxgofUEBiw6W8", - "8KM0qezhPWMhklg/LJz9X+AGXPifU9TvZMGdL0U+Ar9vqUAf3Nt8sK1DF3HuKm6rOW6okOqKRNgCjA2C", - "hW0PalGNlV1ydWcwpfGG6cEh9TCbnNgEgs+XN9q7okq7hxuUylqjeEQBNjyikOk0rBbLxVIbMo4x4RRc", - "+LBYLlZgAycqMPk72Xyn9Tk7TgSJEv3kAU25ulii51XPBvyK6mN5gHElSIQKhQT3trJ+COch9cxg55tk", - "tVXUNT3VhZGhAa5JG+wcBhMZylgqscXkzq6u8fPl8lC8vZ1TI0JiYjoeY39T7EbDWDRgqBKCCxpRRR+1", - "IT7xkPkI7oaEErPCvNxNXhrYJag2TEREpST4cA52gxOJPSiihudAQDw5YhbFt4gQ5HloWFIJSxVGclD8", - "/S9ptJZ8Gml04T1fGntYWE6YQbiwSkLDpKweuhmxC4LjIs5F92olXmpQYNhagcegCYJ+ZklFhKLxg/UP", - "VYEVb6N7I5WtXlayAkRduuvq4uOGbEN1rMJgvE2XWqvAfIq30bUWFtmnMNf5w7RE7dZ6JOEWZV7n9y2K", - "59IKM65VcJ2JaFGxfgLu7Wq5tM+Xyzt7gBg0JffHFJvKTDArXy1Z8QESH0WXvP6WWpwqr0HuJiv+r7Pr", - "0pBZhbYj9NmnTBteRHqbiVxo6/YkXkyID2T1ynLczCrVpnaw5lDnQxm8O5FuFpI5ygs6QrLrPldn68z6", - "7CtVwdlVbv1iMh6SewyzxWEWsLNbGMn6ofNd+vf6sKbStS3PIa/B0xDIBqmezSHDVAhTvlyXMcuPH2NB", - "O3QKmQK1Iex6KXz2e8Z4iMo73QwoDVhSM0N0xdqI149PdVwHOmVd/g9Rb19/lXwjgOtl3ynIvQn6NXjX", - "j84Qvp2Cy6sSLiJK0Kca36jfrUafG4OOkSLqz060tLr5ANsTbRRix+9xPZCNY9jc4JSo9tMofE7a4Hog", - "GkG22fBp7G/UHwDOBLvbe2Zcc3Mbh9oJW9v7YF2VbgOgOW1fe9M840TKm0Cw7UMw5AbkujDvvP8YcX/2", - "KrcbpiP4MyIvLrcOlVyy6unF+Yi8u7lSa0T6qeujOVPrSxQLxS9ynvq4nyEXakag3wXcH1XLHvAkJx5a", - "fm5udbbOajjKqe4wCgRNOkXyLc1Pyo9Nl0+frs6mlO3UTPmFiah3qo1RzywPatfW2/XTw6WHwsh2bS2r", - "F0tqWNu2jtn8l2i1iFME3Jfad7NQr3aeO+MuCk8W0Mr2wgNxum/kXrnBXUv2uEvImpORd5AnKFv6oU71", - "gDGgwbhuDHu7neu0RJgNtcqnMyNgezu967kRKp01+t+u160jX715PRtG9eP9UITeTft6fuSGf7y2bhv4", - "JhrYs6F0BPk6WPceaZbtu1+pCtKbYWe3GgBFY9iMh/3VzKd9jbD5QDTNeytCcCFQiruOk30dqlCqhT4z", - "R4QvCIXkLvk3AAD//w==", + "3FpNb+M2E/4rAt/3VMiWne1JPQXbbZuim6R1gC0Q5MBI44hbSeSSdDaB4f9ekJQsiZL1YUv56C2xhjPP", + "POQzFIfaooAmjKaQSoH8LeIgGE0F6H9WJGEx/JX9pH4JaCohlepPCU/SYzEmqfpPBBEkWP/+zAD5SEhO", + "0ge02+1cFIIIOGGS0BT56NwR2q+Tx3Lo/VcIJFKmxo+O/pEqq6cr89DfIsYpAy6JAXcRlqKRVMIDcLRz", + "0YU4DxMDKnt4T2kMOFUPC2f/57BGPvqfV+TvZcG9qwIPh28bwiFE/m0+2FWhizh3FbdVjGvChbzECTQQ", + "4yJO46YHVlRt5ZZc3WlOSbqmanBMAsgmJ9WB0OeLG+VdEqncoxsQ0lkBfwSOXPQIXJhpWM4X84UypAxS", + "zAjy0Yf5Yr5ELmJYRhq/l823yc/bMsxxslNPHkCnq5LFal7VbKBfQX4sD9CuOE5AAhfIv62sH8xYTAI9", + "2PsqqLWK2qanujAyNpCvYSM3p0FHRmUuJd/A7s6trvGzxeJQvL2dZwlhp2N6AaX/EGhnQ1vUaKgKgnGS", + "EEkelSE8sZiGgPw1jgVkiQW5mzw15JaoWlOeYGlE8OEMuTVN7NxeERU9BwLCyRGzKKGDOcfPfcPiSlgi", + "IRG94u9/MdEa8NRgtPE9HYw9LTQXTC9eaAVQv1Jmh65HbKPguIhTyb2aSWAMCg4bMwgoqpOgnjlCYi5J", + "+uB8JzJy0k1yr0tlo5elqBBhl267uoSwxptYHlthIN2YpdZYYD6lm+RaFRbRVWGu84cmReXWecTxBkSe", + "57cN8OfSCtOuZXSdFdEiY/UE+bfLxcI9Wyzu3B7FoF5yfzTcVGaCOvlqyZKPAIfA28rrb8bi1PIa5W6y", + "5P+eXZeGTFpoW0LPPmW14UVKbx3IubJuBvFihfgAqlcux3VUpjY1kzVFdT6E4N0V6XoimaM8IQvg0YeO", + "lKaz31dXl3mRcZ17uklDBwtHRuBw/N0xWJzMx2GBYiFmNxGnm4fomB3F9ricrTLr2Rcio9llbv1iu0yM", + "7yHO1q7Wl7ed64r6Q+ur/h/2sHohblJPn7f0cfTtIiGf9RlIZ4jGfPcvc5afjoaSduiQNAZrfcT/Uvzs", + "t7ThFJU34glY6rGkJqbokjYJr5uf6rgWdsrbxn9Ievv8q+IbQFyn+k5h7k3Ir6a7bnb66O0UXl5VcAmW", + "nDxZeiNhezX6XBt0TCki4eRCM9lNR9heaIMYO36P66BsmMKmJqcktZ8G8XPSBtdB0QCxTcZPbX8jYQ9y", + "Rtjd3rPi6pvbMNZO2Nreh+qqcutBzWn72pvWGcNCZMfRPhc014V56/XMgJP2q1y+6IblzwCsuHs7lHLJ", + "qqNVGAKw9t6P1ScNjeujNWO1TYqFEhaYxz7uZ8zFShEQthH3Z9WygzzBcABOmJs7rZ09i0cx1hVLwaCG", + "U4Bv6M0SdixcNj5chaaEdmyl/EJ50jnV2qhjlnt1k+3bhPHpUkPRwG6yherFQPXrKtucTX/HZ0UcI+A+", + "1a6LDzvbaa602yQ8WkCrY2zHab8wfOX+uwX2uDtSy8nAK9ITKpv5jqh6wOjRYFzVhr3dzrVJEU3GWuXL", + "ngG0vZ3e9dQMlc4a3W/Xq8aRr968nowj+3jfl6F3076enrn+39atmga+iQb2ZCwdIb4W1b1HmWX77hci", + "I3Mz7G2XPaioDZvwsL+c+LSvGNbfrxrcGx4jH0VSMt/zso9XJQg5V2fmBLM5Jmh3t/s3AAD//w==", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/internal/test/parameters/roundtrip/gin/gen/types.gen.go b/internal/test/parameters/roundtrip/gin/gen/types.gen.go index e73bcb508..d070fe992 100644 --- a/internal/test/parameters/roundtrip/gin/gen/types.gen.go +++ b/internal/test/parameters/roundtrip/gin/gen/types.gen.go @@ -93,6 +93,9 @@ type GetHeaderParams struct { // XComplexObject complex object XComplexObject *ComplexObject `json:"X-Complex-Object,omitempty"` + // XPassThrough non-JSON content, bound as the raw header string + XPassThrough *string `json:"X-Pass-Through,omitempty"` + // N1StartingWithNumber name starting with number N1StartingWithNumber *string `json:"1-Starting-With-Number,omitempty"` } diff --git a/internal/test/parameters/roundtrip/gorilla/gen/server.gen.go b/internal/test/parameters/roundtrip/gorilla/gen/server.gen.go index 489209ea0..69cd221f8 100644 --- a/internal/test/parameters/roundtrip/gorilla/gen/server.gen.go +++ b/internal/test/parameters/roundtrip/gorilla/gen/server.gen.go @@ -466,6 +466,21 @@ func (siw *ServerInterfaceWrapper) GetHeader(w http.ResponseWriter, r *http.Requ } + // ------------- Optional header parameter "X-Pass-Through" ------------- + if valueList, found := headers[http.CanonicalHeaderKey("X-Pass-Through")]; found { + var XPassThrough string + n := len(valueList) + if n != 1 { + siw.ErrorHandlerFunc(w, r, &TooManyValuesForParamError{ParamName: "X-Pass-Through", Count: n}) + return + } + + XPassThrough = valueList[0] + + params.XPassThrough = &XPassThrough + + } + // ------------- Optional header parameter "1-Starting-With-Number" ------------- if valueList, found := headers[http.CanonicalHeaderKey("1-Starting-With-Number")]; found { var N1StartingWithNumber string @@ -1401,28 +1416,28 @@ func HandlerWithOptions(si ServerInterface, options GorillaServerOptions) http.H // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "3FpLb+M2F/0rwv2+VaFYdqYrdRVMp22ATiatA0yBIAtGuo44lUQOSacJDP33gpRkPa2HLeXRXWJd3sch", - "z6F4qR14LOIsxlhJcHcgUHIWSzT/rGnEQ/wz+0n/4rFYYaz0nwqflMNDQmP9n/QCjIj5/ZkjuCCVoPED", - "JElig4/SE5QrymJw4cKSxq+Vx7LY/Tf0FGjT1I+J/pFpq6cv6UN3B1wwjkLRNLlLvxSNxgofUEBiw6W8", - "8KM0qezhPWMhklg/LJz9X+AGXPifU9TvZMGdL0U+Ar9vqUAf3Nt8sK1DF3HuKm6rOW6okOqKRNgCjA2C", - "hW0PalGNlV1ydWcwpfGG6cEh9TCbnNgEgs+XN9q7okq7hxuUylqjeEQBNjyikOk0rBbLxVIbMo4x4RRc", - "+LBYLlZgAycqMPk72Xyn9Tk7TgSJEv3kAU25ulii51XPBvyK6mN5gHElSIQKhQT3trJ+COch9cxg55tk", - "tVXUNT3VhZGhAa5JG+wcBhMZylgqscXkzq6u8fPl8lC8vZ1TI0JiYjoeY39T7EbDWDRgqBKCCxpRRR+1", - "IT7xkPkI7oaEErPCvNxNXhrYJag2TEREpST4cA52gxOJPSiihudAQDw5YhbFt4gQ5HloWFIJSxVGclD8", - "/S9ptJZ8Gml04T1fGntYWE6YQbiwSkLDpKweuhmxC4LjIs5F92olXmpQYNhagcegCYJ+ZklFhKLxg/UP", - "VYEVb6N7I5WtXlayAkRduuvq4uOGbEN1rMJgvE2XWqvAfIq30bUWFtmnMNf5w7RE7dZ6JOEWZV7n9y2K", - "59IKM65VcJ2JaFGxfgLu7Wq5tM+Xyzt7gBg0JffHFJvKTDArXy1Z8QESH0WXvP6WWpwqr0HuJiv+r7Pr", - "0pBZhbYj9NmnTBteRHqbiVxo6/YkXkyID2T1ynLczCrVpnaw5lDnQxm8O5FuFpI5ygs6QrLrPldn68z6", - "7CtVwdlVbv1iMh6SewyzxWEWsLNbGMn6ofNd+vf6sKbStS3PIa/B0xDIBqmezSHDVAhTvlyXMcuPH2NB", - "O3QKmQK1Iex6KXz2e8Z4iMo73QwoDVhSM0N0xdqI149PdVwHOmVd/g9Rb19/lXwjgOtl3ynIvQn6NXjX", - "j84Qvp2Cy6sSLiJK0Kca36jfrUafG4OOkSLqz060tLr5ANsTbRRix+9xPZCNY9jc4JSo9tMofE7a4Hog", - "GkG22fBp7G/UHwDOBLvbe2Zcc3Mbh9oJW9v7YF2VbgOgOW1fe9M840TKm0Cw7UMw5AbkujDvvP8YcX/2", - "KrcbpiP4MyIvLrcOlVyy6unF+Yi8u7lSa0T6qeujOVPrSxQLxS9ynvq4nyEXakag3wXcH1XLHvAkJx5a", - "fm5udbbOajjKqe4wCgRNOkXyLc1Pyo9Nl0+frs6mlO3UTPmFiah3qo1RzywPatfW2/XTw6WHwsh2bS2r", - "F0tqWNu2jtn8l2i1iFME3Jfad7NQr3aeO+MuCk8W0Mr2wgNxum/kXrnBXUv2uEvImpORd5AnKFv6oU71", - "gDGgwbhuDHu7neu0RJgNtcqnMyNgezu967kRKp01+t+u160jX715PRtG9eP9UITeTft6fuSGf7y2bhv4", - "JhrYs6F0BPk6WPceaZbtu1+pCtKbYWe3GgBFY9iMh/3VzKd9jbD5QDTNeytCcCFQiruOk30dqlCqhT4z", - "R4QvCIXkLvk3AAD//w==", + "3FpNb+M2E/4rAt/3VMiWne1JPQXbbZuim6R1gC0Q5MBI44hbSeSSdDaB4f9ekJQsiZL1YUv56C2xhjPP", + "POQzFIfaooAmjKaQSoH8LeIgGE0F6H9WJGEx/JX9pH4JaCohlepPCU/SYzEmqfpPBBEkWP/+zAD5SEhO", + "0ge02+1cFIIIOGGS0BT56NwR2q+Tx3Lo/VcIJFKmxo+O/pEqq6cr89DfIsYpAy6JAXcRlqKRVMIDcLRz", + "0YU4DxMDKnt4T2kMOFUPC2f/57BGPvqfV+TvZcG9qwIPh28bwiFE/m0+2FWhizh3FbdVjGvChbzECTQQ", + "4yJO46YHVlRt5ZZc3WlOSbqmanBMAsgmJ9WB0OeLG+VdEqncoxsQ0lkBfwSOXPQIXJhpWM4X84UypAxS", + "zAjy0Yf5Yr5ELmJYRhq/l823yc/bMsxxslNPHkCnq5LFal7VbKBfQX4sD9CuOE5AAhfIv62sH8xYTAI9", + "2PsqqLWK2qanujAyNpCvYSM3p0FHRmUuJd/A7s6trvGzxeJQvL2dZwlhp2N6AaX/EGhnQ1vUaKgKgnGS", + "EEkelSE8sZiGgPw1jgVkiQW5mzw15JaoWlOeYGlE8OEMuTVN7NxeERU9BwLCyRGzKKGDOcfPfcPiSlgi", + "IRG94u9/MdEa8NRgtPE9HYw9LTQXTC9eaAVQv1Jmh65HbKPguIhTyb2aSWAMCg4bMwgoqpOgnjlCYi5J", + "+uB8JzJy0k1yr0tlo5elqBBhl267uoSwxptYHlthIN2YpdZYYD6lm+RaFRbRVWGu84cmReXWecTxBkSe", + "57cN8OfSCtOuZXSdFdEiY/UE+bfLxcI9Wyzu3B7FoF5yfzTcVGaCOvlqyZKPAIfA28rrb8bi1PIa5W6y", + "5P+eXZeGTFpoW0LPPmW14UVKbx3IubJuBvFihfgAqlcux3VUpjY1kzVFdT6E4N0V6XoimaM8IQvg0YeO", + "lKaz31dXl3mRcZ17uklDBwtHRuBw/N0xWJzMx2GBYiFmNxGnm4fomB3F9ricrTLr2Rcio9llbv1iu0yM", + "7yHO1q7Wl7ed64r6Q+ur/h/2sHohblJPn7f0cfTtIiGf9RlIZ4jGfPcvc5afjoaSduiQNAZrfcT/Uvzs", + "t7ThFJU34glY6rGkJqbokjYJr5uf6rgWdsrbxn9Ievv8q+IbQFyn+k5h7k3Ir6a7bnb66O0UXl5VcAmW", + "nDxZeiNhezX6XBt0TCki4eRCM9lNR9heaIMYO36P66BsmMKmJqcktZ8G8XPSBtdB0QCxTcZPbX8jYQ9y", + "Rtjd3rPi6pvbMNZO2Nreh+qqcutBzWn72pvWGcNCZMfRPhc014V56/XMgJP2q1y+6IblzwCsuHs7lHLJ", + "qqNVGAKw9t6P1ScNjeujNWO1TYqFEhaYxz7uZ8zFShEQthH3Z9WygzzBcABOmJs7rZ09i0cx1hVLwaCG", + "U4Bv6M0SdixcNj5chaaEdmyl/EJ50jnV2qhjlnt1k+3bhPHpUkPRwG6yherFQPXrKtucTX/HZ0UcI+A+", + "1a6LDzvbaa602yQ8WkCrY2zHab8wfOX+uwX2uDtSy8nAK9ITKpv5jqh6wOjRYFzVhr3dzrVJEU3GWuXL", + "ngG0vZ3e9dQMlc4a3W/Xq8aRr968nowj+3jfl6F3076enrn+39atmga+iQb2ZCwdIb4W1b1HmWX77hci", + "I3Mz7G2XPaioDZvwsL+c+LSvGNbfrxrcGx4jH0VSMt/zso9XJQg5V2fmBLM5Jmh3t/s3AAD//w==", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/internal/test/parameters/roundtrip/gorilla/gen/types.gen.go b/internal/test/parameters/roundtrip/gorilla/gen/types.gen.go index b7a27e409..4dc13fdcd 100644 --- a/internal/test/parameters/roundtrip/gorilla/gen/types.gen.go +++ b/internal/test/parameters/roundtrip/gorilla/gen/types.gen.go @@ -93,6 +93,9 @@ type GetHeaderParams struct { // XComplexObject complex object XComplexObject *ComplexObject `json:"X-Complex-Object,omitempty"` + // XPassThrough non-JSON content, bound as the raw header string + XPassThrough *string `json:"X-Pass-Through,omitempty"` + // N1StartingWithNumber name starting with number N1StartingWithNumber *string `json:"1-Starting-With-Number,omitempty"` } diff --git a/internal/test/parameters/roundtrip/iris/gen/server.gen.go b/internal/test/parameters/roundtrip/iris/gen/server.gen.go index cdf8aae2b..3671a78e3 100644 --- a/internal/test/parameters/roundtrip/iris/gen/server.gen.go +++ b/internal/test/parameters/roundtrip/iris/gen/server.gen.go @@ -419,6 +419,20 @@ func (w *ServerInterfaceWrapper) GetHeader(ctx iris.Context) { params.XComplexObject = &XComplexObject } + // ------------- Optional header parameter "X-Pass-Through" ------------- + if valueList, found := headers[http.CanonicalHeaderKey("X-Pass-Through")]; found { + var XPassThrough string + n := len(valueList) + if n != 1 { + ctx.StatusCode(http.StatusBadRequest) + ctx.Writef("Expected one value for X-Pass-Through, got %d", n) + return + } + + XPassThrough = valueList[0] + + params.XPassThrough = &XPassThrough + } // ------------- Optional header parameter "1-Starting-With-Number" ------------- if valueList, found := headers[http.CanonicalHeaderKey("1-Starting-With-Number")]; found { var N1StartingWithNumber string @@ -1040,28 +1054,28 @@ func RegisterHandlersWithOptions(router *iris.Application, si ServerInterface, o // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "3FpLb+M2F/0rwv2+VaFYdqYrdRVMp22ATiatA0yBIAtGuo44lUQOSacJDP33gpRkPa2HLeXRXWJd3sch", - "z6F4qR14LOIsxlhJcHcgUHIWSzT/rGnEQ/wz+0n/4rFYYaz0nwqflMNDQmP9n/QCjIj5/ZkjuCCVoPED", - "JElig4/SE5QrymJw4cKSxq+Vx7LY/Tf0FGjT1I+J/pFpq6cv6UN3B1wwjkLRNLlLvxSNxgofUEBiw6W8", - "8KM0qezhPWMhklg/LJz9X+AGXPifU9TvZMGdL0U+Ar9vqUAf3Nt8sK1DF3HuKm6rOW6okOqKRNgCjA2C", - "hW0PalGNlV1ydWcwpfGG6cEh9TCbnNgEgs+XN9q7okq7hxuUylqjeEQBNjyikOk0rBbLxVIbMo4x4RRc", - "+LBYLlZgAycqMPk72Xyn9Tk7TgSJEv3kAU25ulii51XPBvyK6mN5gHElSIQKhQT3trJ+COch9cxg55tk", - "tVXUNT3VhZGhAa5JG+wcBhMZylgqscXkzq6u8fPl8lC8vZ1TI0JiYjoeY39T7EbDWDRgqBKCCxpRRR+1", - "IT7xkPkI7oaEErPCvNxNXhrYJag2TEREpST4cA52gxOJPSiihudAQDw5YhbFt4gQ5HloWFIJSxVGclD8", - "/S9ptJZ8Gml04T1fGntYWE6YQbiwSkLDpKweuhmxC4LjIs5F92olXmpQYNhagcegCYJ+ZklFhKLxg/UP", - "VYEVb6N7I5WtXlayAkRduuvq4uOGbEN1rMJgvE2XWqvAfIq30bUWFtmnMNf5w7RE7dZ6JOEWZV7n9y2K", - "59IKM65VcJ2JaFGxfgLu7Wq5tM+Xyzt7gBg0JffHFJvKTDArXy1Z8QESH0WXvP6WWpwqr0HuJiv+r7Pr", - "0pBZhbYj9NmnTBteRHqbiVxo6/YkXkyID2T1ynLczCrVpnaw5lDnQxm8O5FuFpI5ygs6QrLrPldn68z6", - "7CtVwdlVbv1iMh6SewyzxWEWsLNbGMn6ofNd+vf6sKbStS3PIa/B0xDIBqmezSHDVAhTvlyXMcuPH2NB", - "O3QKmQK1Iex6KXz2e8Z4iMo73QwoDVhSM0N0xdqI149PdVwHOmVd/g9Rb19/lXwjgOtl3ynIvQn6NXjX", - "j84Qvp2Cy6sSLiJK0Kca36jfrUafG4OOkSLqz060tLr5ANsTbRRix+9xPZCNY9jc4JSo9tMofE7a4Hog", - "GkG22fBp7G/UHwDOBLvbe2Zcc3Mbh9oJW9v7YF2VbgOgOW1fe9M840TKm0Cw7UMw5AbkujDvvP8YcX/2", - "KrcbpiP4MyIvLrcOlVyy6unF+Yi8u7lSa0T6qeujOVPrSxQLxS9ynvq4nyEXakag3wXcH1XLHvAkJx5a", - "fm5udbbOajjKqe4wCgRNOkXyLc1Pyo9Nl0+frs6mlO3UTPmFiah3qo1RzywPatfW2/XTw6WHwsh2bS2r", - "F0tqWNu2jtn8l2i1iFME3Jfad7NQr3aeO+MuCk8W0Mr2wgNxum/kXrnBXUv2uEvImpORd5AnKFv6oU71", - "gDGgwbhuDHu7neu0RJgNtcqnMyNgezu967kRKp01+t+u160jX715PRtG9eP9UITeTft6fuSGf7y2bhv4", - "JhrYs6F0BPk6WPceaZbtu1+pCtKbYWe3GgBFY9iMh/3VzKd9jbD5QDTNeytCcCFQiruOk30dqlCqhT4z", - "R4QvCIXkLvk3AAD//w==", + "3FpNb+M2E/4rAt/3VMiWne1JPQXbbZuim6R1gC0Q5MBI44hbSeSSdDaB4f9ekJQsiZL1YUv56C2xhjPP", + "POQzFIfaooAmjKaQSoH8LeIgGE0F6H9WJGEx/JX9pH4JaCohlepPCU/SYzEmqfpPBBEkWP/+zAD5SEhO", + "0ge02+1cFIIIOGGS0BT56NwR2q+Tx3Lo/VcIJFKmxo+O/pEqq6cr89DfIsYpAy6JAXcRlqKRVMIDcLRz", + "0YU4DxMDKnt4T2kMOFUPC2f/57BGPvqfV+TvZcG9qwIPh28bwiFE/m0+2FWhizh3FbdVjGvChbzECTQQ", + "4yJO46YHVlRt5ZZc3WlOSbqmanBMAsgmJ9WB0OeLG+VdEqncoxsQ0lkBfwSOXPQIXJhpWM4X84UypAxS", + "zAjy0Yf5Yr5ELmJYRhq/l823yc/bMsxxslNPHkCnq5LFal7VbKBfQX4sD9CuOE5AAhfIv62sH8xYTAI9", + "2PsqqLWK2qanujAyNpCvYSM3p0FHRmUuJd/A7s6trvGzxeJQvL2dZwlhp2N6AaX/EGhnQ1vUaKgKgnGS", + "EEkelSE8sZiGgPw1jgVkiQW5mzw15JaoWlOeYGlE8OEMuTVN7NxeERU9BwLCyRGzKKGDOcfPfcPiSlgi", + "IRG94u9/MdEa8NRgtPE9HYw9LTQXTC9eaAVQv1Jmh65HbKPguIhTyb2aSWAMCg4bMwgoqpOgnjlCYi5J", + "+uB8JzJy0k1yr0tlo5elqBBhl267uoSwxptYHlthIN2YpdZYYD6lm+RaFRbRVWGu84cmReXWecTxBkSe", + "57cN8OfSCtOuZXSdFdEiY/UE+bfLxcI9Wyzu3B7FoF5yfzTcVGaCOvlqyZKPAIfA28rrb8bi1PIa5W6y", + "5P+eXZeGTFpoW0LPPmW14UVKbx3IubJuBvFihfgAqlcux3VUpjY1kzVFdT6E4N0V6XoimaM8IQvg0YeO", + "lKaz31dXl3mRcZ17uklDBwtHRuBw/N0xWJzMx2GBYiFmNxGnm4fomB3F9ricrTLr2Rcio9llbv1iu0yM", + "7yHO1q7Wl7ed64r6Q+ur/h/2sHohblJPn7f0cfTtIiGf9RlIZ4jGfPcvc5afjoaSduiQNAZrfcT/Uvzs", + "t7ThFJU34glY6rGkJqbokjYJr5uf6rgWdsrbxn9Ievv8q+IbQFyn+k5h7k3Ir6a7bnb66O0UXl5VcAmW", + "nDxZeiNhezX6XBt0TCki4eRCM9lNR9heaIMYO36P66BsmMKmJqcktZ8G8XPSBtdB0QCxTcZPbX8jYQ9y", + "Rtjd3rPi6pvbMNZO2Nreh+qqcutBzWn72pvWGcNCZMfRPhc014V56/XMgJP2q1y+6IblzwCsuHs7lHLJ", + "qqNVGAKw9t6P1ScNjeujNWO1TYqFEhaYxz7uZ8zFShEQthH3Z9WygzzBcABOmJs7rZ09i0cx1hVLwaCG", + "U4Bv6M0SdixcNj5chaaEdmyl/EJ50jnV2qhjlnt1k+3bhPHpUkPRwG6yherFQPXrKtucTX/HZ0UcI+A+", + "1a6LDzvbaa602yQ8WkCrY2zHab8wfOX+uwX2uDtSy8nAK9ITKpv5jqh6wOjRYFzVhr3dzrVJEU3GWuXL", + "ngG0vZ3e9dQMlc4a3W/Xq8aRr968nowj+3jfl6F3076enrn+39atmga+iQb2ZCwdIb4W1b1HmWX77hci", + "I3Mz7G2XPaioDZvwsL+c+LSvGNbfrxrcGx4jH0VSMt/zso9XJQg5V2fmBLM5Jmh3t/s3AAD//w==", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/internal/test/parameters/roundtrip/iris/gen/types.gen.go b/internal/test/parameters/roundtrip/iris/gen/types.gen.go index b075b62ba..479585951 100644 --- a/internal/test/parameters/roundtrip/iris/gen/types.gen.go +++ b/internal/test/parameters/roundtrip/iris/gen/types.gen.go @@ -93,6 +93,9 @@ type GetHeaderParams struct { // XComplexObject complex object XComplexObject *ComplexObject `json:"X-Complex-Object,omitempty"` + // XPassThrough non-JSON content, bound as the raw header string + XPassThrough *string `json:"X-Pass-Through,omitempty"` + // N1StartingWithNumber name starting with number N1StartingWithNumber *string `json:"1-Starting-With-Number,omitempty"` } diff --git a/internal/test/parameters/roundtrip/param_roundtrip_test.go b/internal/test/parameters/roundtrip/param_roundtrip_test.go index aa027feed..d836fb46f 100644 --- a/internal/test/parameters/roundtrip/param_roundtrip_test.go +++ b/internal/test/parameters/roundtrip/param_roundtrip_test.go @@ -440,6 +440,7 @@ func testImpl(t *testing.T, handler http.Handler) { expectedObject2 := paramclient.Object{FirstName: "Marcin", Role: "annoyed_at_swagger"} var expectedPrimitive2 int32 = 100 var expectedN1s = "111" + var expectedPassThrough = "raw header value" t.Run("all params at once", func(t *testing.T) { params := paramclient.GetHeaderParams{ @@ -450,6 +451,7 @@ func testImpl(t *testing.T, handler http.Handler) { XObjectExploded: &expectedObject, XObject: &expectedObject2, XComplexObject: &expectedComplexObject, + XPassThrough: &expectedPassThrough, N1StartingWithNumber: &expectedN1s, } req, err := paramclient.NewGetHeaderRequest(server, ¶ms) @@ -488,6 +490,19 @@ func testImpl(t *testing.T, handler http.Handler) { require.NotNil(t, got.XObject) assert.Equal(t, expectedObject, *got.XObject) }) + + // Regression: pass-through (non-JSON content) header params used to be + // clobbered with the zero value by the wrapper templates' trailing + // assignment, so the handler always saw "". + t.Run("pass-through only", func(t *testing.T) { + params := paramclient.GetHeaderParams{XPassThrough: &expectedPassThrough} + req, err := paramclient.NewGetHeaderRequest(server, ¶ms) + require.NoError(t, err) + var got paramclient.GetHeaderParams + doRoundTrip(t, req, &got) + require.NotNil(t, got.XPassThrough) + assert.Equal(t, expectedPassThrough, *got.XPassThrough) + }) }) // ========================================================================= diff --git a/internal/test/parameters/roundtrip/parameters.yaml b/internal/test/parameters/roundtrip/parameters.yaml index 7c0963196..8e77ecc4a 100644 --- a/internal/test/parameters/roundtrip/parameters.yaml +++ b/internal/test/parameters/roundtrip/parameters.yaml @@ -509,6 +509,14 @@ paths: application/json: schema: $ref: "#/components/schemas/ComplexObject" + - name: X-Pass-Through + description: non-JSON content, bound as the raw header string + in: header + required: false + content: + text/plain: + schema: + type: string - name: 1-Starting-With-Number description: name starting with number in: header diff --git a/internal/test/parameters/roundtrip/stdhttp/gen/server.gen.go b/internal/test/parameters/roundtrip/stdhttp/gen/server.gen.go index eda097643..e1dab89be 100644 --- a/internal/test/parameters/roundtrip/stdhttp/gen/server.gen.go +++ b/internal/test/parameters/roundtrip/stdhttp/gen/server.gen.go @@ -467,6 +467,21 @@ func (siw *ServerInterfaceWrapper) GetHeader(w http.ResponseWriter, r *http.Requ } + // ------------- Optional header parameter "X-Pass-Through" ------------- + if valueList, found := headers[http.CanonicalHeaderKey("X-Pass-Through")]; found { + var XPassThrough string + n := len(valueList) + if n != 1 { + siw.ErrorHandlerFunc(w, r, &TooManyValuesForParamError{ParamName: "X-Pass-Through", Count: n}) + return + } + + XPassThrough = valueList[0] + + params.XPassThrough = &XPassThrough + + } + // ------------- Optional header parameter "1-Starting-With-Number" ------------- if valueList, found := headers[http.CanonicalHeaderKey("1-Starting-With-Number")]; found { var N1StartingWithNumber string @@ -1383,28 +1398,28 @@ func HandlerWithOptions(si ServerInterface, options StdHTTPServerOptions) http.H // const string: with thousands of chunks the chained `+` fold is several // times slower for the Go compiler than parsing a slice literal. var swaggerSpec = []string{ - "3FpLb+M2F/0rwv2+VaFYdqYrdRVMp22ATiatA0yBIAtGuo44lUQOSacJDP33gpRkPa2HLeXRXWJd3sch", - "z6F4qR14LOIsxlhJcHcgUHIWSzT/rGnEQ/wz+0n/4rFYYaz0nwqflMNDQmP9n/QCjIj5/ZkjuCCVoPED", - "JElig4/SE5QrymJw4cKSxq+Vx7LY/Tf0FGjT1I+J/pFpq6cv6UN3B1wwjkLRNLlLvxSNxgofUEBiw6W8", - "8KM0qezhPWMhklg/LJz9X+AGXPifU9TvZMGdL0U+Ar9vqUAf3Nt8sK1DF3HuKm6rOW6okOqKRNgCjA2C", - "hW0PalGNlV1ydWcwpfGG6cEh9TCbnNgEgs+XN9q7okq7hxuUylqjeEQBNjyikOk0rBbLxVIbMo4x4RRc", - "+LBYLlZgAycqMPk72Xyn9Tk7TgSJEv3kAU25ulii51XPBvyK6mN5gHElSIQKhQT3trJ+COch9cxg55tk", - "tVXUNT3VhZGhAa5JG+wcBhMZylgqscXkzq6u8fPl8lC8vZ1TI0JiYjoeY39T7EbDWDRgqBKCCxpRRR+1", - "IT7xkPkI7oaEErPCvNxNXhrYJag2TEREpST4cA52gxOJPSiihudAQDw5YhbFt4gQ5HloWFIJSxVGclD8", - "/S9ptJZ8Gml04T1fGntYWE6YQbiwSkLDpKweuhmxC4LjIs5F92olXmpQYNhagcegCYJ+ZklFhKLxg/UP", - "VYEVb6N7I5WtXlayAkRduuvq4uOGbEN1rMJgvE2XWqvAfIq30bUWFtmnMNf5w7RE7dZ6JOEWZV7n9y2K", - "59IKM65VcJ2JaFGxfgLu7Wq5tM+Xyzt7gBg0JffHFJvKTDArXy1Z8QESH0WXvP6WWpwqr0HuJiv+r7Pr", - "0pBZhbYj9NmnTBteRHqbiVxo6/YkXkyID2T1ynLczCrVpnaw5lDnQxm8O5FuFpI5ygs6QrLrPldn68z6", - "7CtVwdlVbv1iMh6SewyzxWEWsLNbGMn6ofNd+vf6sKbStS3PIa/B0xDIBqmezSHDVAhTvlyXMcuPH2NB", - "O3QKmQK1Iex6KXz2e8Z4iMo73QwoDVhSM0N0xdqI149PdVwHOmVd/g9Rb19/lXwjgOtl3ynIvQn6NXjX", - "j84Qvp2Cy6sSLiJK0Kca36jfrUafG4OOkSLqz060tLr5ANsTbRRix+9xPZCNY9jc4JSo9tMofE7a4Hog", - "GkG22fBp7G/UHwDOBLvbe2Zcc3Mbh9oJW9v7YF2VbgOgOW1fe9M840TKm0Cw7UMw5AbkujDvvP8YcX/2", - "KrcbpiP4MyIvLrcOlVyy6unF+Yi8u7lSa0T6qeujOVPrSxQLxS9ynvq4nyEXakag3wXcH1XLHvAkJx5a", - "fm5udbbOajjKqe4wCgRNOkXyLc1Pyo9Nl0+frs6mlO3UTPmFiah3qo1RzywPatfW2/XTw6WHwsh2bS2r", - "F0tqWNu2jtn8l2i1iFME3Jfad7NQr3aeO+MuCk8W0Mr2wgNxum/kXrnBXUv2uEvImpORd5AnKFv6oU71", - "gDGgwbhuDHu7neu0RJgNtcqnMyNgezu967kRKp01+t+u160jX715PRtG9eP9UITeTft6fuSGf7y2bhv4", - "JhrYs6F0BPk6WPceaZbtu1+pCtKbYWe3GgBFY9iMh/3VzKd9jbD5QDTNeytCcCFQiruOk30dqlCqhT4z", - "R4QvCIXkLvk3AAD//w==", + "3FpNb+M2E/4rAt/3VMiWne1JPQXbbZuim6R1gC0Q5MBI44hbSeSSdDaB4f9ekJQsiZL1YUv56C2xhjPP", + "POQzFIfaooAmjKaQSoH8LeIgGE0F6H9WJGEx/JX9pH4JaCohlepPCU/SYzEmqfpPBBEkWP/+zAD5SEhO", + "0ge02+1cFIIIOGGS0BT56NwR2q+Tx3Lo/VcIJFKmxo+O/pEqq6cr89DfIsYpAy6JAXcRlqKRVMIDcLRz", + "0YU4DxMDKnt4T2kMOFUPC2f/57BGPvqfV+TvZcG9qwIPh28bwiFE/m0+2FWhizh3FbdVjGvChbzECTQQ", + "4yJO46YHVlRt5ZZc3WlOSbqmanBMAsgmJ9WB0OeLG+VdEqncoxsQ0lkBfwSOXPQIXJhpWM4X84UypAxS", + "zAjy0Yf5Yr5ELmJYRhq/l823yc/bMsxxslNPHkCnq5LFal7VbKBfQX4sD9CuOE5AAhfIv62sH8xYTAI9", + "2PsqqLWK2qanujAyNpCvYSM3p0FHRmUuJd/A7s6trvGzxeJQvL2dZwlhp2N6AaX/EGhnQ1vUaKgKgnGS", + "EEkelSE8sZiGgPw1jgVkiQW5mzw15JaoWlOeYGlE8OEMuTVN7NxeERU9BwLCyRGzKKGDOcfPfcPiSlgi", + "IRG94u9/MdEa8NRgtPE9HYw9LTQXTC9eaAVQv1Jmh65HbKPguIhTyb2aSWAMCg4bMwgoqpOgnjlCYi5J", + "+uB8JzJy0k1yr0tlo5elqBBhl267uoSwxptYHlthIN2YpdZYYD6lm+RaFRbRVWGu84cmReXWecTxBkSe", + "57cN8OfSCtOuZXSdFdEiY/UE+bfLxcI9Wyzu3B7FoF5yfzTcVGaCOvlqyZKPAIfA28rrb8bi1PIa5W6y", + "5P+eXZeGTFpoW0LPPmW14UVKbx3IubJuBvFihfgAqlcux3VUpjY1kzVFdT6E4N0V6XoimaM8IQvg0YeO", + "lKaz31dXl3mRcZ17uklDBwtHRuBw/N0xWJzMx2GBYiFmNxGnm4fomB3F9ricrTLr2Rcio9llbv1iu0yM", + "7yHO1q7Wl7ed64r6Q+ur/h/2sHohblJPn7f0cfTtIiGf9RlIZ4jGfPcvc5afjoaSduiQNAZrfcT/Uvzs", + "t7ThFJU34glY6rGkJqbokjYJr5uf6rgWdsrbxn9Ievv8q+IbQFyn+k5h7k3Ir6a7bnb66O0UXl5VcAmW", + "nDxZeiNhezX6XBt0TCki4eRCM9lNR9heaIMYO36P66BsmMKmJqcktZ8G8XPSBtdB0QCxTcZPbX8jYQ9y", + "Rtjd3rPi6pvbMNZO2Nreh+qqcutBzWn72pvWGcNCZMfRPhc014V56/XMgJP2q1y+6IblzwCsuHs7lHLJ", + "qqNVGAKw9t6P1ScNjeujNWO1TYqFEhaYxz7uZ8zFShEQthH3Z9WygzzBcABOmJs7rZ09i0cx1hVLwaCG", + "U4Bv6M0SdixcNj5chaaEdmyl/EJ50jnV2qhjlnt1k+3bhPHpUkPRwG6yherFQPXrKtucTX/HZ0UcI+A+", + "1a6LDzvbaa602yQ8WkCrY2zHab8wfOX+uwX2uDtSy8nAK9ITKpv5jqh6wOjRYFzVhr3dzrVJEU3GWuXL", + "ngG0vZ3e9dQMlc4a3W/Xq8aRr968nowj+3jfl6F3076enrn+39atmga+iQb2ZCwdIb4W1b1HmWX77hci", + "I3Mz7G2XPaioDZvwsL+c+LSvGNbfrxrcGx4jH0VSMt/zso9XJQg5V2fmBLM5Jmh3t/s3AAD//w==", } // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, diff --git a/internal/test/parameters/roundtrip/stdhttp/gen/types.gen.go b/internal/test/parameters/roundtrip/stdhttp/gen/types.gen.go index 132c9c349..e203ec106 100644 --- a/internal/test/parameters/roundtrip/stdhttp/gen/types.gen.go +++ b/internal/test/parameters/roundtrip/stdhttp/gen/types.gen.go @@ -93,6 +93,9 @@ type GetHeaderParams struct { // XComplexObject complex object XComplexObject *ComplexObject `json:"X-Complex-Object,omitempty"` + // XPassThrough non-JSON content, bound as the raw header string + XPassThrough *string `json:"X-Pass-Through,omitempty"` + // N1StartingWithNumber name starting with number N1StartingWithNumber *string `json:"1-Starting-With-Number,omitempty"` } diff --git a/pkg/codegen/templates/chi/chi-middleware.tmpl b/pkg/codegen/templates/chi/chi-middleware.tmpl index b8392427f..651e389d8 100644 --- a/pkg/codegen/templates/chi/chi-middleware.tmpl +++ b/pkg/codegen/templates/chi/chi-middleware.tmpl @@ -104,7 +104,7 @@ func (siw *ServerInterfaceWrapper) {{$opid}}(w http.ResponseWriter, r *http.Requ } {{if .IsPassThrough}} - params.{{.GoName}} = {{if .HasOptionalPointer }}&{{end}}valueList[0] + {{.GoName}} = valueList[0] {{end}} {{if .IsJson}} diff --git a/pkg/codegen/templates/echo/echo-wrappers.tmpl b/pkg/codegen/templates/echo/echo-wrappers.tmpl index 7d19c91d5..7766928ca 100644 --- a/pkg/codegen/templates/echo/echo-wrappers.tmpl +++ b/pkg/codegen/templates/echo/echo-wrappers.tmpl @@ -72,7 +72,7 @@ func (w *ServerInterfaceWrapper) {{.OperationId}} (ctx echo.Context) error { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Expected one value for {{.ParamName}}, got %d", n)) } {{if .IsPassThrough}} - params.{{.GoName}} = {{if .HasOptionalPointer}}&{{end}}valueList[0] + {{.GoName}} = valueList[0] {{end}} {{if .IsJson}} err = json.Unmarshal([]byte(valueList[0]), &{{.GoName}}) diff --git a/pkg/codegen/templates/echo/v5/echo-wrappers.tmpl b/pkg/codegen/templates/echo/v5/echo-wrappers.tmpl index 8fcab2c66..9f8142ee0 100644 --- a/pkg/codegen/templates/echo/v5/echo-wrappers.tmpl +++ b/pkg/codegen/templates/echo/v5/echo-wrappers.tmpl @@ -72,7 +72,7 @@ func (w *ServerInterfaceWrapper) {{.OperationId}} (ctx *echo.Context) error { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Expected one value for {{.ParamName}}, got %d", n)) } {{if .IsPassThrough}} - params.{{.GoName}} = {{if .HasOptionalPointer}}&{{end}}valueList[0] + {{.GoName}} = valueList[0] {{end}} {{if .IsJson}} err = json.Unmarshal([]byte(valueList[0]), &{{.GoName}}) diff --git a/pkg/codegen/templates/fiber-v3/fiber-middleware.tmpl b/pkg/codegen/templates/fiber-v3/fiber-middleware.tmpl index 122f958e4..0172dd5b2 100644 --- a/pkg/codegen/templates/fiber-v3/fiber-middleware.tmpl +++ b/pkg/codegen/templates/fiber-v3/fiber-middleware.tmpl @@ -111,7 +111,7 @@ func (siw *ServerInterfaceWrapper) {{$opid}}(c fiber.Ctx) error { } {{if .IsPassThrough}} - params.{{.GoName}} = {{if .HasOptionalPointer}}&{{end}}valueList[0] + {{.GoName}} = valueList[0] {{end}} {{if .IsJson}} diff --git a/pkg/codegen/templates/fiber/fiber-middleware.tmpl b/pkg/codegen/templates/fiber/fiber-middleware.tmpl index 533996e73..2625392b9 100644 --- a/pkg/codegen/templates/fiber/fiber-middleware.tmpl +++ b/pkg/codegen/templates/fiber/fiber-middleware.tmpl @@ -111,7 +111,7 @@ func (siw *ServerInterfaceWrapper) {{$opid}}(c *fiber.Ctx) error { } {{if .IsPassThrough}} - params.{{.GoName}} = {{if .HasOptionalPointer}}&{{end}}valueList[0] + {{.GoName}} = valueList[0] {{end}} {{if .IsJson}} diff --git a/pkg/codegen/templates/gin/gin-wrappers.tmpl b/pkg/codegen/templates/gin/gin-wrappers.tmpl index b768c67a9..a100342a4 100644 --- a/pkg/codegen/templates/gin/gin-wrappers.tmpl +++ b/pkg/codegen/templates/gin/gin-wrappers.tmpl @@ -99,7 +99,7 @@ func (siw *ServerInterfaceWrapper) {{$opid}}(c *gin.Context) { } {{if .IsPassThrough}} - params.{{.GoName}} = {{if .HasOptionalPointer}}&{{end}}valueList[0] + {{.GoName}} = valueList[0] {{end}} {{if .IsJson}} diff --git a/pkg/codegen/templates/gorilla/gorilla-middleware.tmpl b/pkg/codegen/templates/gorilla/gorilla-middleware.tmpl index 2ef4b852e..916eb9bde 100644 --- a/pkg/codegen/templates/gorilla/gorilla-middleware.tmpl +++ b/pkg/codegen/templates/gorilla/gorilla-middleware.tmpl @@ -104,7 +104,7 @@ func (siw *ServerInterfaceWrapper) {{$opid}}(w http.ResponseWriter, r *http.Requ } {{if .IsPassThrough}} - params.{{.GoName}} = {{if .HasOptionalPointer}}&{{end}}valueList[0] + {{.GoName}} = valueList[0] {{end}} {{if .IsJson}} diff --git a/pkg/codegen/templates/iris/iris-middleware.tmpl b/pkg/codegen/templates/iris/iris-middleware.tmpl index 46eddccaa..daf41466d 100644 --- a/pkg/codegen/templates/iris/iris-middleware.tmpl +++ b/pkg/codegen/templates/iris/iris-middleware.tmpl @@ -90,7 +90,7 @@ func (w *ServerInterfaceWrapper) {{.OperationId}} (ctx iris.Context) { return } {{if .IsPassThrough}} - params.{{.GoName}} = {{if .HasOptionalPointer}}&{{end}}valueList[0] + {{.GoName}} = valueList[0] {{end}} {{if .IsJson}} err = json.Unmarshal([]byte(valueList[0]), &{{.GoName}}) diff --git a/pkg/codegen/templates/stdhttp/std-http-middleware.tmpl b/pkg/codegen/templates/stdhttp/std-http-middleware.tmpl index 65c62cacb..b9d0a2a5a 100644 --- a/pkg/codegen/templates/stdhttp/std-http-middleware.tmpl +++ b/pkg/codegen/templates/stdhttp/std-http-middleware.tmpl @@ -104,7 +104,7 @@ func (siw *ServerInterfaceWrapper) {{$opid}}(w http.ResponseWriter, r *http.Requ } {{if .IsPassThrough}} - params.{{.GoName}} = {{if .HasOptionalPointer}}&{{end}}valueList[0] + {{.GoName}} = valueList[0] {{end}} {{if .IsJson}} From b952d35ce52ade55c60fde6f4071e33476b0e477 Mon Sep 17 00:00:00 2001 From: Marcin Romaszewicz Date: Thu, 9 Jul 2026 16:16:32 -0700 Subject: [PATCH 5/8] fix: drop nil error wrap in fiber required-header message The fiber v2 and v3 wrappers built the required-header-missing message with fmt.Errorf("...: %w", err), but in that branch the header was simply absent -- err is nil (rendering "%!w()" in the response) or stale from a previously bound parameter, leaking an unrelated error into the message. Return the plain message instead, matching the fiber receiver template and every other backend. Co-Authored-By: Claude Fable 5 --- internal/test/servers/strict/fiber/server.gen.go | 3 +-- pkg/codegen/templates/fiber-v3/fiber-middleware.tmpl | 3 +-- pkg/codegen/templates/fiber/fiber-middleware.tmpl | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/internal/test/servers/strict/fiber/server.gen.go b/internal/test/servers/strict/fiber/server.gen.go index e66757304..807c66031 100644 --- a/internal/test/servers/strict/fiber/server.gen.go +++ b/internal/test/servers/strict/fiber/server.gen.go @@ -385,8 +385,7 @@ func (siw *ServerInterfaceWrapper) HeadersExample(c *fiber.Ctx) error { params.Header1 = Header1 } else { - err = fmt.Errorf("Header parameter header1 is required, but not found: %w", err) - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return fiber.NewError(fiber.StatusBadRequest, "Header parameter header1 is required, but not found") } // ------------- Optional header parameter "header2" ------------- diff --git a/pkg/codegen/templates/fiber-v3/fiber-middleware.tmpl b/pkg/codegen/templates/fiber-v3/fiber-middleware.tmpl index 0172dd5b2..8ed9ac742 100644 --- a/pkg/codegen/templates/fiber-v3/fiber-middleware.tmpl +++ b/pkg/codegen/templates/fiber-v3/fiber-middleware.tmpl @@ -131,8 +131,7 @@ func (siw *ServerInterfaceWrapper) {{$opid}}(c fiber.Ctx) error { params.{{.GoName}} = {{if .HasOptionalPointer}}&{{end}}{{.GoName}} } {{if .Required}}else { - err = fmt.Errorf("Header parameter {{.ParamName}} is required, but not found: %w", err) - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return fiber.NewError(fiber.StatusBadRequest, "Header parameter {{.ParamName}} is required, but not found") }{{end}} {{end}} diff --git a/pkg/codegen/templates/fiber/fiber-middleware.tmpl b/pkg/codegen/templates/fiber/fiber-middleware.tmpl index 2625392b9..de0b4995f 100644 --- a/pkg/codegen/templates/fiber/fiber-middleware.tmpl +++ b/pkg/codegen/templates/fiber/fiber-middleware.tmpl @@ -131,8 +131,7 @@ func (siw *ServerInterfaceWrapper) {{$opid}}(c *fiber.Ctx) error { params.{{.GoName}} = {{if .HasOptionalPointer}}&{{end}}{{.GoName}} } {{if .Required}}else { - err = fmt.Errorf("Header parameter {{.ParamName}} is required, but not found: %w", err) - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return fiber.NewError(fiber.StatusBadRequest, "Header parameter {{.ParamName}} is required, but not found") }{{end}} {{end}} From e6666687fa958915366782d9b91de8b43a8531b5 Mon Sep 17 00:00:00 2001 From: Marcin Romaszewicz Date: Thu, 9 Jul 2026 16:18:28 -0700 Subject: [PATCH 6/8] fix: return fiber.NewError for missing required query param The fiber v2 and v3 wrappers handled a missing required pass-through or JSON-content query parameter by writing c.Status(400).JSON(err) -- which marshals a bare error to "{}" -- and then also returning the raw error, so fiber's default error handler ran again on the already-written response and reported 500 for a client error. Return fiber.NewError(400, ...) instead, matching every sibling binding branch and the fiber receiver template. Co-Authored-By: Claude Fable 5 --- pkg/codegen/templates/fiber-v3/fiber-middleware.tmpl | 4 +--- pkg/codegen/templates/fiber/fiber-middleware.tmpl | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/pkg/codegen/templates/fiber-v3/fiber-middleware.tmpl b/pkg/codegen/templates/fiber-v3/fiber-middleware.tmpl index 8ed9ac742..042a15802 100644 --- a/pkg/codegen/templates/fiber-v3/fiber-middleware.tmpl +++ b/pkg/codegen/templates/fiber-v3/fiber-middleware.tmpl @@ -86,9 +86,7 @@ func (siw *ServerInterfaceWrapper) {{$opid}}(c fiber.Ctx) error { params.{{.GoName}} = {{if .HasOptionalPointer}}&{{end}}value {{end}} }{{if .Required}} else { - err = fmt.Errorf("Query argument {{.ParamName}} is required, but not found") - c.Status(fiber.StatusBadRequest).JSON(err) - return err + return fiber.NewError(fiber.StatusBadRequest, "Query argument {{.ParamName}} is required, but not found") }{{end}} {{end}} {{if .IsStyled}} diff --git a/pkg/codegen/templates/fiber/fiber-middleware.tmpl b/pkg/codegen/templates/fiber/fiber-middleware.tmpl index de0b4995f..9766d074f 100644 --- a/pkg/codegen/templates/fiber/fiber-middleware.tmpl +++ b/pkg/codegen/templates/fiber/fiber-middleware.tmpl @@ -86,9 +86,7 @@ func (siw *ServerInterfaceWrapper) {{$opid}}(c *fiber.Ctx) error { params.{{.GoName}} = {{if .HasOptionalPointer}}&{{end}}value {{end}} }{{if .Required}} else { - err = fmt.Errorf("Query argument {{.ParamName}} is required, but not found") - c.Status(fiber.StatusBadRequest).JSON(err) - return err + return fiber.NewError(fiber.StatusBadRequest, "Query argument {{.ParamName}} is required, but not found") }{{end}} {{end}} {{if .IsStyled}} From 065b59475973e06eec5c9b410cb2b5e1591d7851 Mon Sep 17 00:00:00 2001 From: Marcin Romaszewicz Date: Thu, 9 Jul 2026 16:24:06 -0700 Subject: [PATCH 7/8] fix: report strict handler errors as server errors The fiber v2/v3 and iris strict handlers reported errors returned by the user's handler -- and failures while writing the response -- as HTTP 400, conflating server-side failures with client errors. Every other backend reports these as 500. Iris additionally wrote the "unexpected response type" message without setting any status code, producing an implicit 200. Fiber now returns the raw error into fiber's error chain (matching echo): the default error handler yields 500, custom app error handlers receive the untouched error, and handlers that deliberately return a *fiber.Error keep control of their status. Iris now uses StopWithError(500, ...) for all three failure paths. Adds runtime regression tests for fiber and iris asserting a handler error surfaces as 500; both fail against the previous templates. Co-Authored-By: Claude Fable 5 --- .../servers/routers/smoke/fiber/out.gen.go | 16 ++-- .../servers/routers/smoke/iris/out.gen.go | 25 ++--- .../servers/strict/fiber/fiber_strict_test.go | 22 +++++ .../test/servers/strict/fiber/server.gen.go | 64 ++++++------- .../servers/strict/iris/iris_strict_test.go | 33 +++++++ .../test/servers/strict/iris/server.gen.go | 96 +++++++++---------- .../serversstrictmulticontentfiber.gen.go | 4 +- .../iris/serversstrictmulticontentiris.gen.go | 6 +- .../templates/strict/strict-fiber-v3.tmpl | 4 +- .../templates/strict/strict-fiber.tmpl | 4 +- pkg/codegen/templates/strict/strict-iris.tmpl | 6 +- 11 files changed, 168 insertions(+), 112 deletions(-) create mode 100644 internal/test/servers/strict/iris/iris_strict_test.go diff --git a/internal/test/servers/routers/smoke/fiber/out.gen.go b/internal/test/servers/routers/smoke/fiber/out.gen.go index d2867215a..03c0d8217 100644 --- a/internal/test/servers/routers/smoke/fiber/out.gen.go +++ b/internal/test/servers/routers/smoke/fiber/out.gen.go @@ -261,10 +261,10 @@ func (sh *strictHandler) GetGetMultibody(ctx *fiber.Ctx) error { response, err := handler(ctx, request) if err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } else if validResponse, ok := response.(GetGetMultibodyResponseObject); ok { if err := validResponse.VisitGetGetMultibodyResponse(ctx); err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } } else if response != nil { return fmt.Errorf("unexpected response type: %T", response) @@ -286,10 +286,10 @@ func (sh *strictHandler) GetObject(ctx *fiber.Ctx) error { response, err := handler(ctx, request) if err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } else if validResponse, ok := response.(GetObjectResponseObject); ok { if err := validResponse.VisitGetObjectResponse(ctx); err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } } else if response != nil { return fmt.Errorf("unexpected response type: %T", response) @@ -334,10 +334,10 @@ func (sh *strictHandler) PostPostMultibody(ctx *fiber.Ctx) error { response, err := handler(ctx, request) if err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } else if validResponse, ok := response.(PostPostMultibodyResponseObject); ok { if err := validResponse.VisitPostPostMultibodyResponse(ctx); err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } } else if response != nil { return fmt.Errorf("unexpected response type: %T", response) @@ -368,10 +368,10 @@ func (sh *strictHandler) PostPostObject(ctx *fiber.Ctx) error { response, err := handler(ctx, request) if err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } else if validResponse, ok := response.(PostPostObjectResponseObject); ok { if err := validResponse.VisitPostPostObjectResponse(ctx); err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } } else if response != nil { return fmt.Errorf("unexpected response type: %T", response) diff --git a/internal/test/servers/routers/smoke/iris/out.gen.go b/internal/test/servers/routers/smoke/iris/out.gen.go index 054e264f7..9d5e46bb0 100644 --- a/internal/test/servers/routers/smoke/iris/out.gen.go +++ b/internal/test/servers/routers/smoke/iris/out.gen.go @@ -6,6 +6,7 @@ package iris import ( "context" "errors" + "fmt" "io" "net/http" "strings" @@ -211,15 +212,15 @@ func (sh *strictHandler) GetGetMultibody(ctx iris.Context) { response, err := handler(ctx, request) if err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } else if validResponse, ok := response.(GetGetMultibodyResponseObject); ok { if err := validResponse.VisitGetGetMultibodyResponse(ctx); err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } } else if response != nil { - ctx.Writef("Unexpected response type: %T", response) + ctx.StopWithError(http.StatusInternalServerError, fmt.Errorf("unexpected response type: %T", response)) return } } @@ -238,15 +239,15 @@ func (sh *strictHandler) GetObject(ctx iris.Context) { response, err := handler(ctx, request) if err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } else if validResponse, ok := response.(GetObjectResponseObject); ok { if err := validResponse.VisitGetObjectResponse(ctx); err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } } else if response != nil { - ctx.Writef("Unexpected response type: %T", response) + ctx.StopWithError(http.StatusInternalServerError, fmt.Errorf("unexpected response type: %T", response)) return } } @@ -290,15 +291,15 @@ func (sh *strictHandler) PostPostMultibody(ctx iris.Context) { response, err := handler(ctx, request) if err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } else if validResponse, ok := response.(PostPostMultibodyResponseObject); ok { if err := validResponse.VisitPostPostMultibodyResponse(ctx); err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } } else if response != nil { - ctx.Writef("Unexpected response type: %T", response) + ctx.StopWithError(http.StatusInternalServerError, fmt.Errorf("unexpected response type: %T", response)) return } } @@ -327,15 +328,15 @@ func (sh *strictHandler) PostPostObject(ctx iris.Context) { response, err := handler(ctx, request) if err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } else if validResponse, ok := response.(PostPostObjectResponseObject); ok { if err := validResponse.VisitPostPostObjectResponse(ctx); err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } } else if response != nil { - ctx.Writef("Unexpected response type: %T", response) + ctx.StopWithError(http.StatusInternalServerError, fmt.Errorf("unexpected response type: %T", response)) return } } diff --git a/internal/test/servers/strict/fiber/fiber_strict_test.go b/internal/test/servers/strict/fiber/fiber_strict_test.go index d47e8aebf..054ac50cd 100644 --- a/internal/test/servers/strict/fiber/fiber_strict_test.go +++ b/internal/test/servers/strict/fiber/fiber_strict_test.go @@ -2,7 +2,9 @@ package api import ( "bytes" + "context" "encoding/json" + "errors" "io" "mime" "mime/multipart" @@ -28,6 +30,26 @@ func TestFiberServer(t *testing.T) { testImpl(t, adaptor.FiberApp(r)) } +type erroringServer struct{ StrictServer } + +func (erroringServer) JSONExample(ctx context.Context, request JSONExampleRequestObject) (JSONExampleResponseObject, error) { + return nil, errors.New("handler failure") +} + +// Errors returned by strict handlers used to be wrapped in +// fiber.NewError(StatusBadRequest, ...); they must reach fiber's error +// chain untouched, where the default handler reports them as 500. +func TestFiberHandlerErrorIsServerError(t *testing.T) { + strictHandler := NewStrictHandler(erroringServer{}, nil) + r := fiber.New() + RegisterHandlers(r, strictHandler) + + value := "123" + requestBody := clientAPI.Example{Value: &value} + rr := testutil.NewRequest().Post("/json").WithJsonBody(requestBody).GoWithHTTPHandler(t, adaptor.FiberApp(r)).Recorder + assert.Equal(t, http.StatusInternalServerError, rr.Code) +} + func testImpl(t *testing.T, handler http.Handler) { t.Run("JSONExample", func(t *testing.T) { value := "123" diff --git a/internal/test/servers/strict/fiber/server.gen.go b/internal/test/servers/strict/fiber/server.gen.go index 807c66031..19532d2db 100644 --- a/internal/test/servers/strict/fiber/server.gen.go +++ b/internal/test/servers/strict/fiber/server.gen.go @@ -1230,10 +1230,10 @@ func (sh *strictHandler) JSONExample(ctx *fiber.Ctx) error { response, err := handler(ctx, request) if err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } else if validResponse, ok := response.(JSONExampleResponseObject); ok { if err := validResponse.VisitJSONExampleResponse(ctx); err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } } else if response != nil { return fmt.Errorf("unexpected response type: %T", response) @@ -1257,10 +1257,10 @@ func (sh *strictHandler) MultipartExample(ctx *fiber.Ctx) error { response, err := handler(ctx, request) if err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } else if validResponse, ok := response.(MultipartExampleResponseObject); ok { if err := validResponse.VisitMultipartExampleResponse(ctx); err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } } else if response != nil { return fmt.Errorf("unexpected response type: %T", response) @@ -1290,10 +1290,10 @@ func (sh *strictHandler) MultipartRelatedExample(ctx *fiber.Ctx) error { response, err := handler(ctx, request) if err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } else if validResponse, ok := response.(MultipartRelatedExampleResponseObject); ok { if err := validResponse.VisitMultipartRelatedExampleResponse(ctx); err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } } else if response != nil { return fmt.Errorf("unexpected response type: %T", response) @@ -1347,10 +1347,10 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(ctx *fiber.Ctx) error { response, err := handler(ctx, request) if err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } else if validResponse, ok := response.(MultipleRequestAndResponseTypesResponseObject); ok { if err := validResponse.VisitMultipleRequestAndResponseTypesResponse(ctx); err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } } else if response != nil { return fmt.Errorf("unexpected response type: %T", response) @@ -1372,10 +1372,10 @@ func (sh *strictHandler) NoContentHeaders(ctx *fiber.Ctx) error { response, err := handler(ctx, request) if err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } else if validResponse, ok := response.(NoContentHeadersResponseObject); ok { if err := validResponse.VisitNoContentHeadersResponse(ctx); err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } } else if response != nil { return fmt.Errorf("unexpected response type: %T", response) @@ -1403,10 +1403,10 @@ func (sh *strictHandler) RequiredJSONBody(ctx *fiber.Ctx) error { response, err := handler(ctx, request) if err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } else if validResponse, ok := response.(RequiredJSONBodyResponseObject); ok { if err := validResponse.VisitRequiredJSONBodyResponse(ctx); err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } } else if response != nil { return fmt.Errorf("unexpected response type: %T", response) @@ -1432,10 +1432,10 @@ func (sh *strictHandler) RequiredTextBody(ctx *fiber.Ctx) error { response, err := handler(ctx, request) if err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } else if validResponse, ok := response.(RequiredTextBodyResponseObject); ok { if err := validResponse.VisitRequiredTextBodyResponse(ctx); err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } } else if response != nil { return fmt.Errorf("unexpected response type: %T", response) @@ -1459,10 +1459,10 @@ func (sh *strictHandler) ReservedGoKeywordParameters(ctx *fiber.Ctx, pType strin response, err := handler(ctx, request) if err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } else if validResponse, ok := response.(ReservedGoKeywordParametersResponseObject); ok { if err := validResponse.VisitReservedGoKeywordParametersResponse(ctx); err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } } else if response != nil { return fmt.Errorf("unexpected response type: %T", response) @@ -1493,10 +1493,10 @@ func (sh *strictHandler) ReusableResponses(ctx *fiber.Ctx) error { response, err := handler(ctx, request) if err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } else if validResponse, ok := response.(ReusableResponsesResponseObject); ok { if err := validResponse.VisitReusableResponsesResponse(ctx); err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } } else if response != nil { return fmt.Errorf("unexpected response type: %T", response) @@ -1529,10 +1529,10 @@ func (sh *strictHandler) SameNameParamAndBodyProperty(ctx *fiber.Ctx, name strin response, err := handler(ctx, request) if err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } else if validResponse, ok := response.(SameNameParamAndBodyPropertyResponseObject); ok { if err := validResponse.VisitSameNameParamAndBodyPropertyResponse(ctx); err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } } else if response != nil { return fmt.Errorf("unexpected response type: %T", response) @@ -1560,10 +1560,10 @@ func (sh *strictHandler) TextExample(ctx *fiber.Ctx) error { response, err := handler(ctx, request) if err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } else if validResponse, ok := response.(TextExampleResponseObject); ok { if err := validResponse.VisitTextExampleResponse(ctx); err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } } else if response != nil { return fmt.Errorf("unexpected response type: %T", response) @@ -1587,10 +1587,10 @@ func (sh *strictHandler) UnknownExample(ctx *fiber.Ctx) error { response, err := handler(ctx, request) if err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } else if validResponse, ok := response.(UnknownExampleResponseObject); ok { if err := validResponse.VisitUnknownExampleResponse(ctx); err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } } else if response != nil { return fmt.Errorf("unexpected response type: %T", response) @@ -1616,10 +1616,10 @@ func (sh *strictHandler) UnspecifiedContentType(ctx *fiber.Ctx) error { response, err := handler(ctx, request) if err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } else if validResponse, ok := response.(UnspecifiedContentTypeResponseObject); ok { if err := validResponse.VisitUnspecifiedContentTypeResponse(ctx); err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } } else if response != nil { return fmt.Errorf("unexpected response type: %T", response) @@ -1647,10 +1647,10 @@ func (sh *strictHandler) URLEncodedExample(ctx *fiber.Ctx) error { response, err := handler(ctx, request) if err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } else if validResponse, ok := response.(URLEncodedExampleResponseObject); ok { if err := validResponse.VisitURLEncodedExampleResponse(ctx); err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } } else if response != nil { return fmt.Errorf("unexpected response type: %T", response) @@ -1683,10 +1683,10 @@ func (sh *strictHandler) HeadersExample(ctx *fiber.Ctx, params HeadersExamplePar response, err := handler(ctx, request) if err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } else if validResponse, ok := response.(HeadersExampleResponseObject); ok { if err := validResponse.VisitHeadersExampleResponse(ctx); err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } } else if response != nil { return fmt.Errorf("unexpected response type: %T", response) @@ -1717,10 +1717,10 @@ func (sh *strictHandler) UnionExample(ctx *fiber.Ctx) error { response, err := handler(ctx, request) if err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } else if validResponse, ok := response.(UnionExampleResponseObject); ok { if err := validResponse.VisitUnionExampleResponse(ctx); err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } } else if response != nil { return fmt.Errorf("unexpected response type: %T", response) diff --git a/internal/test/servers/strict/iris/iris_strict_test.go b/internal/test/servers/strict/iris/iris_strict_test.go new file mode 100644 index 000000000..203c4a5ff --- /dev/null +++ b/internal/test/servers/strict/iris/iris_strict_test.go @@ -0,0 +1,33 @@ +package api + +import ( + "context" + "errors" + "net/http" + "testing" + + "github.com/kataras/iris/v12" + "github.com/stretchr/testify/assert" + + clientAPI "github.com/oapi-codegen/oapi-codegen/v2/internal/test/servers/strict/client" + "github.com/oapi-codegen/testutil" +) + +type erroringServer struct{ StrictServer } + +func (erroringServer) JSONExample(ctx context.Context, request JSONExampleRequestObject) (JSONExampleResponseObject, error) { + return nil, errors.New("handler failure") +} + +// Errors returned by strict handlers used to be reported via +// ctx.StopWithError(StatusBadRequest, ...); they are server-side +// failures and must be reported as 500. +func TestIrisHandlerErrorIsServerError(t *testing.T) { + app := iris.New() + RegisterHandlers(app, NewStrictHandler(erroringServer{}, nil)) + + value := "123" + requestBody := clientAPI.Example{Value: &value} + rr := testutil.NewRequest().Post("/json").WithJsonBody(requestBody).GoWithHTTPHandler(t, app).Recorder + assert.Equal(t, http.StatusInternalServerError, rr.Code) +} diff --git a/internal/test/servers/strict/iris/server.gen.go b/internal/test/servers/strict/iris/server.gen.go index 3de9ea6cd..e6aefeeb2 100644 --- a/internal/test/servers/strict/iris/server.gen.go +++ b/internal/test/servers/strict/iris/server.gen.go @@ -1047,15 +1047,15 @@ func (sh *strictHandler) JSONExample(ctx iris.Context) { response, err := handler(ctx, request) if err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } else if validResponse, ok := response.(JSONExampleResponseObject); ok { if err := validResponse.VisitJSONExampleResponse(ctx); err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } } else if response != nil { - ctx.Writef("Unexpected response type: %T", response) + ctx.StopWithError(http.StatusInternalServerError, fmt.Errorf("unexpected response type: %T", response)) return } } @@ -1081,15 +1081,15 @@ func (sh *strictHandler) MultipartExample(ctx iris.Context) { response, err := handler(ctx, request) if err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } else if validResponse, ok := response.(MultipartExampleResponseObject); ok { if err := validResponse.VisitMultipartExampleResponse(ctx); err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } } else if response != nil { - ctx.Writef("Unexpected response type: %T", response) + ctx.StopWithError(http.StatusInternalServerError, fmt.Errorf("unexpected response type: %T", response)) return } } @@ -1118,15 +1118,15 @@ func (sh *strictHandler) MultipartRelatedExample(ctx iris.Context) { response, err := handler(ctx, request) if err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } else if validResponse, ok := response.(MultipartRelatedExampleResponseObject); ok { if err := validResponse.VisitMultipartRelatedExampleResponse(ctx); err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } } else if response != nil { - ctx.Writef("Unexpected response type: %T", response) + ctx.StopWithError(http.StatusInternalServerError, fmt.Errorf("unexpected response type: %T", response)) return } } @@ -1192,15 +1192,15 @@ func (sh *strictHandler) MultipleRequestAndResponseTypes(ctx iris.Context) { response, err := handler(ctx, request) if err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } else if validResponse, ok := response.(MultipleRequestAndResponseTypesResponseObject); ok { if err := validResponse.VisitMultipleRequestAndResponseTypesResponse(ctx); err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } } else if response != nil { - ctx.Writef("Unexpected response type: %T", response) + ctx.StopWithError(http.StatusInternalServerError, fmt.Errorf("unexpected response type: %T", response)) return } } @@ -1219,15 +1219,15 @@ func (sh *strictHandler) NoContentHeaders(ctx iris.Context) { response, err := handler(ctx, request) if err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } else if validResponse, ok := response.(NoContentHeadersResponseObject); ok { if err := validResponse.VisitNoContentHeadersResponse(ctx); err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } } else if response != nil { - ctx.Writef("Unexpected response type: %T", response) + ctx.StopWithError(http.StatusInternalServerError, fmt.Errorf("unexpected response type: %T", response)) return } } @@ -1253,15 +1253,15 @@ func (sh *strictHandler) RequiredJSONBody(ctx iris.Context) { response, err := handler(ctx, request) if err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } else if validResponse, ok := response.(RequiredJSONBodyResponseObject); ok { if err := validResponse.VisitRequiredJSONBodyResponse(ctx); err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } } else if response != nil { - ctx.Writef("Unexpected response type: %T", response) + ctx.StopWithError(http.StatusInternalServerError, fmt.Errorf("unexpected response type: %T", response)) return } } @@ -1288,15 +1288,15 @@ func (sh *strictHandler) RequiredTextBody(ctx iris.Context) { response, err := handler(ctx, request) if err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } else if validResponse, ok := response.(RequiredTextBodyResponseObject); ok { if err := validResponse.VisitRequiredTextBodyResponse(ctx); err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } } else if response != nil { - ctx.Writef("Unexpected response type: %T", response) + ctx.StopWithError(http.StatusInternalServerError, fmt.Errorf("unexpected response type: %T", response)) return } } @@ -1317,15 +1317,15 @@ func (sh *strictHandler) ReservedGoKeywordParameters(ctx iris.Context, pType str response, err := handler(ctx, request) if err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } else if validResponse, ok := response.(ReservedGoKeywordParametersResponseObject); ok { if err := validResponse.VisitReservedGoKeywordParametersResponse(ctx); err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } } else if response != nil { - ctx.Writef("Unexpected response type: %T", response) + ctx.StopWithError(http.StatusInternalServerError, fmt.Errorf("unexpected response type: %T", response)) return } } @@ -1354,15 +1354,15 @@ func (sh *strictHandler) ReusableResponses(ctx iris.Context) { response, err := handler(ctx, request) if err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } else if validResponse, ok := response.(ReusableResponsesResponseObject); ok { if err := validResponse.VisitReusableResponsesResponse(ctx); err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } } else if response != nil { - ctx.Writef("Unexpected response type: %T", response) + ctx.StopWithError(http.StatusInternalServerError, fmt.Errorf("unexpected response type: %T", response)) return } } @@ -1393,15 +1393,15 @@ func (sh *strictHandler) SameNameParamAndBodyProperty(ctx iris.Context, name str response, err := handler(ctx, request) if err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } else if validResponse, ok := response.(SameNameParamAndBodyPropertyResponseObject); ok { if err := validResponse.VisitSameNameParamAndBodyPropertyResponse(ctx); err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } } else if response != nil { - ctx.Writef("Unexpected response type: %T", response) + ctx.StopWithError(http.StatusInternalServerError, fmt.Errorf("unexpected response type: %T", response)) return } } @@ -1430,15 +1430,15 @@ func (sh *strictHandler) TextExample(ctx iris.Context) { response, err := handler(ctx, request) if err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } else if validResponse, ok := response.(TextExampleResponseObject); ok { if err := validResponse.VisitTextExampleResponse(ctx); err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } } else if response != nil { - ctx.Writef("Unexpected response type: %T", response) + ctx.StopWithError(http.StatusInternalServerError, fmt.Errorf("unexpected response type: %T", response)) return } } @@ -1459,15 +1459,15 @@ func (sh *strictHandler) UnknownExample(ctx iris.Context) { response, err := handler(ctx, request) if err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } else if validResponse, ok := response.(UnknownExampleResponseObject); ok { if err := validResponse.VisitUnknownExampleResponse(ctx); err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } } else if response != nil { - ctx.Writef("Unexpected response type: %T", response) + ctx.StopWithError(http.StatusInternalServerError, fmt.Errorf("unexpected response type: %T", response)) return } } @@ -1490,15 +1490,15 @@ func (sh *strictHandler) UnspecifiedContentType(ctx iris.Context) { response, err := handler(ctx, request) if err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } else if validResponse, ok := response.(UnspecifiedContentTypeResponseObject); ok { if err := validResponse.VisitUnspecifiedContentTypeResponse(ctx); err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } } else if response != nil { - ctx.Writef("Unexpected response type: %T", response) + ctx.StopWithError(http.StatusInternalServerError, fmt.Errorf("unexpected response type: %T", response)) return } } @@ -1528,15 +1528,15 @@ func (sh *strictHandler) URLEncodedExample(ctx iris.Context) { response, err := handler(ctx, request) if err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } else if validResponse, ok := response.(URLEncodedExampleResponseObject); ok { if err := validResponse.VisitURLEncodedExampleResponse(ctx); err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } } else if response != nil { - ctx.Writef("Unexpected response type: %T", response) + ctx.StopWithError(http.StatusInternalServerError, fmt.Errorf("unexpected response type: %T", response)) return } } @@ -1567,15 +1567,15 @@ func (sh *strictHandler) HeadersExample(ctx iris.Context, params HeadersExampleP response, err := handler(ctx, request) if err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } else if validResponse, ok := response.(HeadersExampleResponseObject); ok { if err := validResponse.VisitHeadersExampleResponse(ctx); err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } } else if response != nil { - ctx.Writef("Unexpected response type: %T", response) + ctx.StopWithError(http.StatusInternalServerError, fmt.Errorf("unexpected response type: %T", response)) return } } @@ -1604,15 +1604,15 @@ func (sh *strictHandler) UnionExample(ctx iris.Context) { response, err := handler(ctx, request) if err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } else if validResponse, ok := response.(UnionExampleResponseObject); ok { if err := validResponse.VisitUnionExampleResponse(ctx); err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } } else if response != nil { - ctx.Writef("Unexpected response type: %T", response) + ctx.StopWithError(http.StatusInternalServerError, fmt.Errorf("unexpected response type: %T", response)) return } } diff --git a/internal/test/servers/strict/multicontent/fiber/serversstrictmulticontentfiber.gen.go b/internal/test/servers/strict/multicontent/fiber/serversstrictmulticontentfiber.gen.go index 215b87e81..2383875c2 100644 --- a/internal/test/servers/strict/multicontent/fiber/serversstrictmulticontentfiber.gen.go +++ b/internal/test/servers/strict/multicontent/fiber/serversstrictmulticontentfiber.gen.go @@ -425,10 +425,10 @@ func (sh *strictHandler) Test(ctx *fiber.Ctx) error { response, err := handler(ctx, request) if err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } else if validResponse, ok := response.(TestResponseObject); ok { if err := validResponse.VisitTestResponse(ctx); err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } } else if response != nil { return fmt.Errorf("unexpected response type: %T", response) diff --git a/internal/test/servers/strict/multicontent/iris/serversstrictmulticontentiris.gen.go b/internal/test/servers/strict/multicontent/iris/serversstrictmulticontentiris.gen.go index c7093ed8a..ccaec9ff4 100644 --- a/internal/test/servers/strict/multicontent/iris/serversstrictmulticontentiris.gen.go +++ b/internal/test/servers/strict/multicontent/iris/serversstrictmulticontentiris.gen.go @@ -411,15 +411,15 @@ func (sh *strictHandler) Test(ctx iris.Context) { response, err := handler(ctx, request) if err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } else if validResponse, ok := response.(TestResponseObject); ok { if err := validResponse.VisitTestResponse(ctx); err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } } else if response != nil { - ctx.Writef("Unexpected response type: %T", response) + ctx.StopWithError(http.StatusInternalServerError, fmt.Errorf("unexpected response type: %T", response)) return } } diff --git a/pkg/codegen/templates/strict/strict-fiber-v3.tmpl b/pkg/codegen/templates/strict/strict-fiber-v3.tmpl index 6ef8f3874..d4f154258 100644 --- a/pkg/codegen/templates/strict/strict-fiber-v3.tmpl +++ b/pkg/codegen/templates/strict/strict-fiber-v3.tmpl @@ -78,10 +78,10 @@ type strictHandler struct { response, err := handler(ctx, request) if err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } else if validResponse, ok := response.({{$opid | ucFirst}}ResponseObject); ok { if err := validResponse.Visit{{$opid}}Response(ctx); err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } } else if response != nil { return fmt.Errorf("unexpected response type: %T", response) diff --git a/pkg/codegen/templates/strict/strict-fiber.tmpl b/pkg/codegen/templates/strict/strict-fiber.tmpl index 0bdc9af82..2bd4e6bf7 100644 --- a/pkg/codegen/templates/strict/strict-fiber.tmpl +++ b/pkg/codegen/templates/strict/strict-fiber.tmpl @@ -90,10 +90,10 @@ type strictHandler struct { response, err := handler(ctx, request) if err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } else if validResponse, ok := response.({{$opid | ucFirst}}ResponseObject); ok { if err := validResponse.Visit{{$opid}}Response(ctx); err != nil { - return fiber.NewError(fiber.StatusBadRequest, err.Error()) + return err } } else if response != nil { return fmt.Errorf("unexpected response type: %T", response) diff --git a/pkg/codegen/templates/strict/strict-iris.tmpl b/pkg/codegen/templates/strict/strict-iris.tmpl index 5195c251b..404db7e23 100644 --- a/pkg/codegen/templates/strict/strict-iris.tmpl +++ b/pkg/codegen/templates/strict/strict-iris.tmpl @@ -107,15 +107,15 @@ type strictHandler struct { response, err := handler(ctx, request) if err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } else if validResponse, ok := response.({{$opid | ucFirst}}ResponseObject); ok { if err := validResponse.Visit{{$opid}}Response(ctx); err != nil { - ctx.StopWithError(http.StatusBadRequest, err) + ctx.StopWithError(http.StatusInternalServerError, err) return } } else if response != nil { - ctx.Writef("Unexpected response type: %T", response) + ctx.StopWithError(http.StatusInternalServerError, fmt.Errorf("unexpected response type: %T", response)) return } } From a0f2c26344a626a781812dcc2c979d57f47bbcce Mon Sep 17 00:00:00 2001 From: Marcin Romaszewicz Date: Thu, 9 Jul 2026 16:29:38 -0700 Subject: [PATCH 8/8] fix: default nil error handlers in NewStrictHandlerWithOptions The shared strict template for chi, gorilla and stdhttp stored the caller's StrictHTTPServerOptions verbatim, so leaving either error handler nil (e.g. passing a zero-value options struct) caused a nil-function panic on the first request or response error. Fill in the same defaults NewStrictHandler already uses (400 for request errors, 500 for response errors), matching what the gin strict template does. Co-Authored-By: Claude Fable 5 --- examples/import-mapping/samepackage/server.gen.go | 10 ++++++++++ .../strict/api/petstore-server.gen.go | 10 ++++++++++ examples/streaming/stdhttp/sse/streaming.gen.go | 10 ++++++++++ internal/test/aggregates/oneof/union.gen.go | 10 ++++++++++ .../content_types/text_and_json/text_and_json.gen.go | 10 ++++++++++ internal/test/bodies/responses/headers/headers.gen.go | 10 ++++++++++ .../external/path_item_refs/bionicle/bionicle.gen.go | 10 ++++++++++ .../external/path_item_refs/common/common.gen.go | 10 ++++++++++ .../path_item_refs/fooservice/fooservice.gen.go | 10 ++++++++++ .../gen/spec_base/issue.gen.go | 10 ++++++++++ .../gen/spec_ext/issue.gen.go | 10 ++++++++++ .../external/removed_ref/gen/spec_base/issue.gen.go | 10 ++++++++++ .../external/removed_ref/gen/spec_ext/issue.gen.go | 10 ++++++++++ .../multipackage/default_response/gen/api/api.gen.go | 10 ++++++++++ .../response_cast/gen/spec_base/issue.gen.go | 10 ++++++++++ .../response_cast/gen/spec_other/issue.gen.go | 10 ++++++++++ internal/test/schemas/deprecated/deprecated.gen.go | 10 ++++++++++ internal/test/schemas/objects/objects.gen.go | 10 ++++++++++ internal/test/servers/routers/smoke/chi/out.gen.go | 10 ++++++++++ internal/test/servers/routers/smoke/gorilla/out.gen.go | 10 ++++++++++ .../test/servers/routers/smoke/std-http/out.gen.go | 10 ++++++++++ .../strict/buffering/serversstrictbuffering.gen.go | 10 ++++++++++ internal/test/servers/strict/chi/server.gen.go | 10 ++++++++++ internal/test/servers/strict/gorilla/server.gen.go | 10 ++++++++++ internal/test/servers/strict/stdhttp/server.gen.go | 10 ++++++++++ pkg/codegen/templates/strict/strict-http.tmpl | 10 ++++++++++ 26 files changed, 260 insertions(+) diff --git a/examples/import-mapping/samepackage/server.gen.go b/examples/import-mapping/samepackage/server.gen.go index f0dd6d85b..4b40b2cb7 100644 --- a/examples/import-mapping/samepackage/server.gen.go +++ b/examples/import-mapping/samepackage/server.gen.go @@ -236,6 +236,16 @@ func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareF } func NewStrictHandlerWithOptions(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc, options StrictHTTPServerOptions) ServerInterface { + if options.RequestErrorHandlerFunc == nil { + options.RequestErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusBadRequest) + } + } + if options.ResponseErrorHandlerFunc == nil { + options.ResponseErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + } return &strictHandler{ssi: ssi, middlewares: middlewares, options: options} } diff --git a/examples/petstore-expanded/strict/api/petstore-server.gen.go b/examples/petstore-expanded/strict/api/petstore-server.gen.go index 52ff32f09..2b1a1a05a 100644 --- a/examples/petstore-expanded/strict/api/petstore-server.gen.go +++ b/examples/petstore-expanded/strict/api/petstore-server.gen.go @@ -543,6 +543,16 @@ func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareF } func NewStrictHandlerWithOptions(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc, options StrictHTTPServerOptions) ServerInterface { + if options.RequestErrorHandlerFunc == nil { + options.RequestErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusBadRequest) + } + } + if options.ResponseErrorHandlerFunc == nil { + options.ResponseErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + } return &strictHandler{ssi: ssi, middlewares: middlewares, options: options} } diff --git a/examples/streaming/stdhttp/sse/streaming.gen.go b/examples/streaming/stdhttp/sse/streaming.gen.go index 01e0792df..d75ba2b5c 100644 --- a/examples/streaming/stdhttp/sse/streaming.gen.go +++ b/examples/streaming/stdhttp/sse/streaming.gen.go @@ -252,6 +252,16 @@ func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareF } func NewStrictHandlerWithOptions(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc, options StrictHTTPServerOptions) ServerInterface { + if options.RequestErrorHandlerFunc == nil { + options.RequestErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusBadRequest) + } + } + if options.ResponseErrorHandlerFunc == nil { + options.ResponseErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + } return &strictHandler{ssi: ssi, middlewares: middlewares, options: options} } diff --git a/internal/test/aggregates/oneof/union.gen.go b/internal/test/aggregates/oneof/union.gen.go index 999e294d7..8daaa3ee7 100644 --- a/internal/test/aggregates/oneof/union.gen.go +++ b/internal/test/aggregates/oneof/union.gen.go @@ -341,6 +341,16 @@ func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareF } func NewStrictHandlerWithOptions(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc, options StrictHTTPServerOptions) ServerInterface { + if options.RequestErrorHandlerFunc == nil { + options.RequestErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusBadRequest) + } + } + if options.ResponseErrorHandlerFunc == nil { + options.ResponseErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + } return &strictHandler{ssi: ssi, middlewares: middlewares, options: options} } diff --git a/internal/test/bodies/content_types/text_and_json/text_and_json.gen.go b/internal/test/bodies/content_types/text_and_json/text_and_json.gen.go index 15a62ab57..76143f5ab 100644 --- a/internal/test/bodies/content_types/text_and_json/text_and_json.gen.go +++ b/internal/test/bodies/content_types/text_and_json/text_and_json.gen.go @@ -483,6 +483,16 @@ func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareF } func NewStrictHandlerWithOptions(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc, options StrictHTTPServerOptions) ServerInterface { + if options.RequestErrorHandlerFunc == nil { + options.RequestErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusBadRequest) + } + } + if options.ResponseErrorHandlerFunc == nil { + options.ResponseErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + } return &strictHandler{ssi: ssi, middlewares: middlewares, options: options} } diff --git a/internal/test/bodies/responses/headers/headers.gen.go b/internal/test/bodies/responses/headers/headers.gen.go index d0587d2d1..3d0004f5d 100644 --- a/internal/test/bodies/responses/headers/headers.gen.go +++ b/internal/test/bodies/responses/headers/headers.gen.go @@ -214,6 +214,16 @@ func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareF } func NewStrictHandlerWithOptions(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc, options StrictHTTPServerOptions) ServerInterface { + if options.RequestErrorHandlerFunc == nil { + options.RequestErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusBadRequest) + } + } + if options.ResponseErrorHandlerFunc == nil { + options.ResponseErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + } return &strictHandler{ssi: ssi, middlewares: middlewares, options: options} } diff --git a/internal/test/references/external/path_item_refs/bionicle/bionicle.gen.go b/internal/test/references/external/path_item_refs/bionicle/bionicle.gen.go index cc9d332ea..fe26501dc 100644 --- a/internal/test/references/external/path_item_refs/bionicle/bionicle.gen.go +++ b/internal/test/references/external/path_item_refs/bionicle/bionicle.gen.go @@ -293,6 +293,16 @@ func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareF } func NewStrictHandlerWithOptions(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc, options StrictHTTPServerOptions) ServerInterface { + if options.RequestErrorHandlerFunc == nil { + options.RequestErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusBadRequest) + } + } + if options.ResponseErrorHandlerFunc == nil { + options.ResponseErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + } return &strictHandler{ssi: ssi, middlewares: middlewares, options: options} } diff --git a/internal/test/references/external/path_item_refs/common/common.gen.go b/internal/test/references/external/path_item_refs/common/common.gen.go index 91da73aeb..ffbf01101 100644 --- a/internal/test/references/external/path_item_refs/common/common.gen.go +++ b/internal/test/references/external/path_item_refs/common/common.gen.go @@ -171,6 +171,16 @@ func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareF } func NewStrictHandlerWithOptions(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc, options StrictHTTPServerOptions) ServerInterface { + if options.RequestErrorHandlerFunc == nil { + options.RequestErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusBadRequest) + } + } + if options.ResponseErrorHandlerFunc == nil { + options.ResponseErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + } return &strictHandler{ssi: ssi, middlewares: middlewares, options: options} } diff --git a/internal/test/references/external/path_item_refs/fooservice/fooservice.gen.go b/internal/test/references/external/path_item_refs/fooservice/fooservice.gen.go index fa95a0dce..37e19cf67 100644 --- a/internal/test/references/external/path_item_refs/fooservice/fooservice.gen.go +++ b/internal/test/references/external/path_item_refs/fooservice/fooservice.gen.go @@ -253,6 +253,16 @@ func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareF } func NewStrictHandlerWithOptions(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc, options StrictHTTPServerOptions) ServerInterface { + if options.RequestErrorHandlerFunc == nil { + options.RequestErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusBadRequest) + } + } + if options.ResponseErrorHandlerFunc == nil { + options.ResponseErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + } return &strictHandler{ssi: ssi, middlewares: middlewares, options: options} } diff --git a/internal/test/references/external/path_item_response_qualification/gen/spec_base/issue.gen.go b/internal/test/references/external/path_item_response_qualification/gen/spec_base/issue.gen.go index c36883c4e..f3c56a9c1 100644 --- a/internal/test/references/external/path_item_response_qualification/gen/spec_base/issue.gen.go +++ b/internal/test/references/external/path_item_response_qualification/gen/spec_base/issue.gen.go @@ -649,6 +649,16 @@ func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareF } func NewStrictHandlerWithOptions(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc, options StrictHTTPServerOptions) ServerInterface { + if options.RequestErrorHandlerFunc == nil { + options.RequestErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusBadRequest) + } + } + if options.ResponseErrorHandlerFunc == nil { + options.ResponseErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + } return &strictHandler{ssi: ssi, middlewares: middlewares, options: options} } diff --git a/internal/test/references/external/path_item_response_qualification/gen/spec_ext/issue.gen.go b/internal/test/references/external/path_item_response_qualification/gen/spec_ext/issue.gen.go index 18d504550..db4a68535 100644 --- a/internal/test/references/external/path_item_response_qualification/gen/spec_ext/issue.gen.go +++ b/internal/test/references/external/path_item_response_qualification/gen/spec_ext/issue.gen.go @@ -173,6 +173,16 @@ func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareF } func NewStrictHandlerWithOptions(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc, options StrictHTTPServerOptions) ServerInterface { + if options.RequestErrorHandlerFunc == nil { + options.RequestErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusBadRequest) + } + } + if options.ResponseErrorHandlerFunc == nil { + options.ResponseErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + } return &strictHandler{ssi: ssi, middlewares: middlewares, options: options} } diff --git a/internal/test/references/external/removed_ref/gen/spec_base/issue.gen.go b/internal/test/references/external/removed_ref/gen/spec_base/issue.gen.go index 6d31cc804..3268820f3 100644 --- a/internal/test/references/external/removed_ref/gen/spec_base/issue.gen.go +++ b/internal/test/references/external/removed_ref/gen/spec_base/issue.gen.go @@ -287,6 +287,16 @@ func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareF } func NewStrictHandlerWithOptions(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc, options StrictHTTPServerOptions) ServerInterface { + if options.RequestErrorHandlerFunc == nil { + options.RequestErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusBadRequest) + } + } + if options.ResponseErrorHandlerFunc == nil { + options.ResponseErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + } return &strictHandler{ssi: ssi, middlewares: middlewares, options: options} } diff --git a/internal/test/references/external/removed_ref/gen/spec_ext/issue.gen.go b/internal/test/references/external/removed_ref/gen/spec_ext/issue.gen.go index b7809cd96..058e91a80 100644 --- a/internal/test/references/external/removed_ref/gen/spec_ext/issue.gen.go +++ b/internal/test/references/external/removed_ref/gen/spec_ext/issue.gen.go @@ -185,6 +185,16 @@ func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareF } func NewStrictHandlerWithOptions(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc, options StrictHTTPServerOptions) ServerInterface { + if options.RequestErrorHandlerFunc == nil { + options.RequestErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusBadRequest) + } + } + if options.ResponseErrorHandlerFunc == nil { + options.ResponseErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + } return &strictHandler{ssi: ssi, middlewares: middlewares, options: options} } diff --git a/internal/test/references/multipackage/default_response/gen/api/api.gen.go b/internal/test/references/multipackage/default_response/gen/api/api.gen.go index 43b8c3239..3807ae73c 100644 --- a/internal/test/references/multipackage/default_response/gen/api/api.gen.go +++ b/internal/test/references/multipackage/default_response/gen/api/api.gen.go @@ -254,6 +254,16 @@ func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareF } func NewStrictHandlerWithOptions(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc, options StrictHTTPServerOptions) ServerInterface { + if options.RequestErrorHandlerFunc == nil { + options.RequestErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusBadRequest) + } + } + if options.ResponseErrorHandlerFunc == nil { + options.ResponseErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + } return &strictHandler{ssi: ssi, middlewares: middlewares, options: options} } diff --git a/internal/test/references/multipackage/response_cast/gen/spec_base/issue.gen.go b/internal/test/references/multipackage/response_cast/gen/spec_base/issue.gen.go index 95fefde7d..94baaa8c5 100644 --- a/internal/test/references/multipackage/response_cast/gen/spec_base/issue.gen.go +++ b/internal/test/references/multipackage/response_cast/gen/spec_base/issue.gen.go @@ -237,6 +237,16 @@ func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareF } func NewStrictHandlerWithOptions(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc, options StrictHTTPServerOptions) ServerInterface { + if options.RequestErrorHandlerFunc == nil { + options.RequestErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusBadRequest) + } + } + if options.ResponseErrorHandlerFunc == nil { + options.ResponseErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + } return &strictHandler{ssi: ssi, middlewares: middlewares, options: options} } diff --git a/internal/test/references/multipackage/response_cast/gen/spec_other/issue.gen.go b/internal/test/references/multipackage/response_cast/gen/spec_other/issue.gen.go index 79deccb92..1840d9f1c 100644 --- a/internal/test/references/multipackage/response_cast/gen/spec_other/issue.gen.go +++ b/internal/test/references/multipackage/response_cast/gen/spec_other/issue.gen.go @@ -229,6 +229,16 @@ func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareF } func NewStrictHandlerWithOptions(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc, options StrictHTTPServerOptions) ServerInterface { + if options.RequestErrorHandlerFunc == nil { + options.RequestErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusBadRequest) + } + } + if options.ResponseErrorHandlerFunc == nil { + options.ResponseErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + } return &strictHandler{ssi: ssi, middlewares: middlewares, options: options} } diff --git a/internal/test/schemas/deprecated/deprecated.gen.go b/internal/test/schemas/deprecated/deprecated.gen.go index 51b76c457..26bade466 100644 --- a/internal/test/schemas/deprecated/deprecated.gen.go +++ b/internal/test/schemas/deprecated/deprecated.gen.go @@ -1975,6 +1975,16 @@ func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareF } func NewStrictHandlerWithOptions(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc, options StrictHTTPServerOptions) ServerInterface { + if options.RequestErrorHandlerFunc == nil { + options.RequestErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusBadRequest) + } + } + if options.ResponseErrorHandlerFunc == nil { + options.ResponseErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + } return &strictHandler{ssi: ssi, middlewares: middlewares, options: options} } diff --git a/internal/test/schemas/objects/objects.gen.go b/internal/test/schemas/objects/objects.gen.go index 7f621e979..dea233f15 100644 --- a/internal/test/schemas/objects/objects.gen.go +++ b/internal/test/schemas/objects/objects.gen.go @@ -935,6 +935,16 @@ func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareF } func NewStrictHandlerWithOptions(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc, options StrictHTTPServerOptions) ServerInterface { + if options.RequestErrorHandlerFunc == nil { + options.RequestErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusBadRequest) + } + } + if options.ResponseErrorHandlerFunc == nil { + options.ResponseErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + } return &strictHandler{ssi: ssi, middlewares: middlewares, options: options} } diff --git a/internal/test/servers/routers/smoke/chi/out.gen.go b/internal/test/servers/routers/smoke/chi/out.gen.go index 29b13ef98..09e3483a1 100644 --- a/internal/test/servers/routers/smoke/chi/out.gen.go +++ b/internal/test/servers/routers/smoke/chi/out.gen.go @@ -377,6 +377,16 @@ func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareF } func NewStrictHandlerWithOptions(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc, options StrictHTTPServerOptions) ServerInterface { + if options.RequestErrorHandlerFunc == nil { + options.RequestErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusBadRequest) + } + } + if options.ResponseErrorHandlerFunc == nil { + options.ResponseErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + } return &strictHandler{ssi: ssi, middlewares: middlewares, options: options} } diff --git a/internal/test/servers/routers/smoke/gorilla/out.gen.go b/internal/test/servers/routers/smoke/gorilla/out.gen.go index 254b183a0..985d886e6 100644 --- a/internal/test/servers/routers/smoke/gorilla/out.gen.go +++ b/internal/test/servers/routers/smoke/gorilla/out.gen.go @@ -348,6 +348,16 @@ func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareF } func NewStrictHandlerWithOptions(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc, options StrictHTTPServerOptions) ServerInterface { + if options.RequestErrorHandlerFunc == nil { + options.RequestErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusBadRequest) + } + } + if options.ResponseErrorHandlerFunc == nil { + options.ResponseErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + } return &strictHandler{ssi: ssi, middlewares: middlewares, options: options} } diff --git a/internal/test/servers/routers/smoke/std-http/out.gen.go b/internal/test/servers/routers/smoke/std-http/out.gen.go index 4fc5ab39c..d4f928d3d 100644 --- a/internal/test/servers/routers/smoke/std-http/out.gen.go +++ b/internal/test/servers/routers/smoke/std-http/out.gen.go @@ -352,6 +352,16 @@ func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareF } func NewStrictHandlerWithOptions(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc, options StrictHTTPServerOptions) ServerInterface { + if options.RequestErrorHandlerFunc == nil { + options.RequestErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusBadRequest) + } + } + if options.ResponseErrorHandlerFunc == nil { + options.ResponseErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + } return &strictHandler{ssi: ssi, middlewares: middlewares, options: options} } diff --git a/internal/test/servers/strict/buffering/serversstrictbuffering.gen.go b/internal/test/servers/strict/buffering/serversstrictbuffering.gen.go index a6400da7a..b17dd3058 100644 --- a/internal/test/servers/strict/buffering/serversstrictbuffering.gen.go +++ b/internal/test/servers/strict/buffering/serversstrictbuffering.gen.go @@ -424,6 +424,16 @@ func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareF } func NewStrictHandlerWithOptions(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc, options StrictHTTPServerOptions) ServerInterface { + if options.RequestErrorHandlerFunc == nil { + options.RequestErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusBadRequest) + } + } + if options.ResponseErrorHandlerFunc == nil { + options.ResponseErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + } return &strictHandler{ssi: ssi, middlewares: middlewares, options: options} } diff --git a/internal/test/servers/strict/chi/server.gen.go b/internal/test/servers/strict/chi/server.gen.go index aff67e9c5..87dbbca6a 100644 --- a/internal/test/servers/strict/chi/server.gen.go +++ b/internal/test/servers/strict/chi/server.gen.go @@ -1402,6 +1402,16 @@ func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareF } func NewStrictHandlerWithOptions(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc, options StrictHTTPServerOptions) ServerInterface { + if options.RequestErrorHandlerFunc == nil { + options.RequestErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusBadRequest) + } + } + if options.ResponseErrorHandlerFunc == nil { + options.ResponseErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + } return &strictHandler{ssi: ssi, middlewares: middlewares, options: options} } diff --git a/internal/test/servers/strict/gorilla/server.gen.go b/internal/test/servers/strict/gorilla/server.gen.go index f9ef3f7f3..d5d7c8412 100644 --- a/internal/test/servers/strict/gorilla/server.gen.go +++ b/internal/test/servers/strict/gorilla/server.gen.go @@ -1301,6 +1301,16 @@ func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareF } func NewStrictHandlerWithOptions(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc, options StrictHTTPServerOptions) ServerInterface { + if options.RequestErrorHandlerFunc == nil { + options.RequestErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusBadRequest) + } + } + if options.ResponseErrorHandlerFunc == nil { + options.ResponseErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + } return &strictHandler{ssi: ssi, middlewares: middlewares, options: options} } diff --git a/internal/test/servers/strict/stdhttp/server.gen.go b/internal/test/servers/strict/stdhttp/server.gen.go index a390586d4..62e17e871 100644 --- a/internal/test/servers/strict/stdhttp/server.gen.go +++ b/internal/test/servers/strict/stdhttp/server.gen.go @@ -1294,6 +1294,16 @@ func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareF } func NewStrictHandlerWithOptions(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc, options StrictHTTPServerOptions) ServerInterface { + if options.RequestErrorHandlerFunc == nil { + options.RequestErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusBadRequest) + } + } + if options.ResponseErrorHandlerFunc == nil { + options.ResponseErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + } return &strictHandler{ssi: ssi, middlewares: middlewares, options: options} } diff --git a/pkg/codegen/templates/strict/strict-http.tmpl b/pkg/codegen/templates/strict/strict-http.tmpl index 062e5459e..8e6166cc9 100644 --- a/pkg/codegen/templates/strict/strict-http.tmpl +++ b/pkg/codegen/templates/strict/strict-http.tmpl @@ -18,6 +18,16 @@ func NewStrictHandler(ssi StrictServerInterface, middlewares []StrictMiddlewareF } func NewStrictHandlerWithOptions(ssi StrictServerInterface, middlewares []StrictMiddlewareFunc, options StrictHTTPServerOptions) ServerInterface { + if options.RequestErrorHandlerFunc == nil { + options.RequestErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusBadRequest) + } + } + if options.ResponseErrorHandlerFunc == nil { + options.ResponseErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + } return &strictHandler{ssi: ssi, middlewares: middlewares, options: options} }