feat(api): expose reusable OpenAPI response components
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
fb7702df67
commit
69dd16cba6
2 changed files with 106 additions and 0 deletions
73
openapi.go
73
openapi.go
|
|
@ -182,6 +182,7 @@ func (sb *SpecBuilder) Build(groups []RouteGroup) ([]byte, error) {
|
|||
},
|
||||
"securitySchemes": securitySchemeComponents(sb.SecuritySchemes),
|
||||
"headers": deprecationHeaderComponents(),
|
||||
"responses": responseComponents(),
|
||||
}
|
||||
|
||||
return json.MarshalIndent(spec, "", " ")
|
||||
|
|
@ -631,6 +632,78 @@ func deprecationHeaderComponents() map[string]any {
|
|||
}
|
||||
}
|
||||
|
||||
// responseComponents returns reusable OpenAPI response objects for the
|
||||
// common error cases exposed by the framework. The path operations still
|
||||
// inline their concrete headers so existing callers keep the same output,
|
||||
// but these components make the response catalogue available for reuse.
|
||||
func responseComponents() map[string]any {
|
||||
return map[string]any{
|
||||
"BadRequest": map[string]any{
|
||||
"description": "Bad request",
|
||||
"content": map[string]any{
|
||||
"application/json": map[string]any{
|
||||
"schema": envelopeSchema(nil),
|
||||
},
|
||||
},
|
||||
"headers": standardResponseHeaders(),
|
||||
},
|
||||
"Unauthorized": map[string]any{
|
||||
"description": "Unauthorised",
|
||||
"content": map[string]any{
|
||||
"application/json": map[string]any{
|
||||
"schema": envelopeSchema(nil),
|
||||
},
|
||||
},
|
||||
"headers": standardResponseHeaders(),
|
||||
},
|
||||
"Forbidden": map[string]any{
|
||||
"description": "Forbidden",
|
||||
"content": map[string]any{
|
||||
"application/json": map[string]any{
|
||||
"schema": envelopeSchema(nil),
|
||||
},
|
||||
},
|
||||
"headers": standardResponseHeaders(),
|
||||
},
|
||||
"RateLimitExceeded": map[string]any{
|
||||
"description": "Too many requests",
|
||||
"content": map[string]any{
|
||||
"application/json": map[string]any{
|
||||
"schema": envelopeSchema(nil),
|
||||
},
|
||||
},
|
||||
"headers": mergeHeaders(standardResponseHeaders(), rateLimitHeaders()),
|
||||
},
|
||||
"GatewayTimeout": map[string]any{
|
||||
"description": "Gateway timeout",
|
||||
"content": map[string]any{
|
||||
"application/json": map[string]any{
|
||||
"schema": envelopeSchema(nil),
|
||||
},
|
||||
},
|
||||
"headers": standardResponseHeaders(),
|
||||
},
|
||||
"InternalServerError": map[string]any{
|
||||
"description": "Internal server error",
|
||||
"content": map[string]any{
|
||||
"application/json": map[string]any{
|
||||
"schema": envelopeSchema(nil),
|
||||
},
|
||||
},
|
||||
"headers": standardResponseHeaders(),
|
||||
},
|
||||
"Gone": map[string]any{
|
||||
"description": "Gone",
|
||||
"content": map[string]any{
|
||||
"application/json": map[string]any{
|
||||
"schema": envelopeSchema(nil),
|
||||
},
|
||||
},
|
||||
"headers": mergeHeaders(standardResponseHeaders(), deprecationResponseHeaders(true, "", "")),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// securitySchemeComponents builds the OpenAPI security scheme registry.
|
||||
// bearerAuth stays available by default, while callers can add or override
|
||||
// additional scheme definitions for custom security requirements.
|
||||
|
|
|
|||
|
|
@ -257,6 +257,39 @@ func TestSpecBuilder_Good_CustomSecuritySchemesAreMerged(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestSpecBuilder_Good_CommonResponseComponentsArePublished(t *testing.T) {
|
||||
sb := &api.SpecBuilder{
|
||||
Title: "Test",
|
||||
Version: "1.0.0",
|
||||
}
|
||||
|
||||
data, err := sb.Build(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
var spec map[string]any
|
||||
if err := json.Unmarshal(data, &spec); err != nil {
|
||||
t.Fatalf("invalid JSON: %v", err)
|
||||
}
|
||||
|
||||
components := spec["components"].(map[string]any)
|
||||
responses := components["responses"].(map[string]any)
|
||||
for _, name := range []string{
|
||||
"BadRequest",
|
||||
"Unauthorized",
|
||||
"Forbidden",
|
||||
"RateLimitExceeded",
|
||||
"GatewayTimeout",
|
||||
"InternalServerError",
|
||||
"Gone",
|
||||
} {
|
||||
if _, ok := responses[name]; !ok {
|
||||
t.Fatalf("expected %s response component in spec", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSpecBuilder_Good_SwaggerUIPathExtension(t *testing.T) {
|
||||
sb := &api.SpecBuilder{
|
||||
Title: "Test",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue