feat(api): document cache hits in OpenAPI
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
f6349145bc
commit
164a1d4f0e
2 changed files with 30 additions and 4 deletions
26
openapi.go
26
openapi.go
|
|
@ -129,7 +129,7 @@ func (sb *SpecBuilder) buildPaths(groups []RouteGroup) map[string]any {
|
|||
"bearerAuth": []any{},
|
||||
},
|
||||
},
|
||||
"responses": operationResponses(rd.Response),
|
||||
"responses": operationResponses(method, rd.Response),
|
||||
}
|
||||
|
||||
// Add request body for methods that accept one.
|
||||
|
|
@ -170,7 +170,12 @@ func (sb *SpecBuilder) buildPaths(groups []RouteGroup) map[string]any {
|
|||
// operationResponses builds the standard response set for a documented API
|
||||
// operation. The framework always exposes the common envelope responses, plus
|
||||
// middleware-driven 429 and 504 errors.
|
||||
func operationResponses(dataSchema map[string]any) map[string]any {
|
||||
func operationResponses(method string, dataSchema map[string]any) map[string]any {
|
||||
successHeaders := mergeHeaders(standardResponseHeaders(), rateLimitSuccessHeaders())
|
||||
if method == "get" {
|
||||
successHeaders = mergeHeaders(successHeaders, cacheSuccessHeaders())
|
||||
}
|
||||
|
||||
return map[string]any{
|
||||
"200": map[string]any{
|
||||
"description": "Successful response",
|
||||
|
|
@ -179,7 +184,7 @@ func operationResponses(dataSchema map[string]any) map[string]any {
|
|||
"schema": envelopeSchema(dataSchema),
|
||||
},
|
||||
},
|
||||
"headers": mergeHeaders(standardResponseHeaders(), rateLimitSuccessHeaders()),
|
||||
"headers": successHeaders,
|
||||
},
|
||||
"400": map[string]any{
|
||||
"description": "Bad request",
|
||||
|
|
@ -249,7 +254,7 @@ func healthResponses() map[string]any {
|
|||
"schema": envelopeSchema(map[string]any{"type": "string"}),
|
||||
},
|
||||
},
|
||||
"headers": mergeHeaders(standardResponseHeaders(), rateLimitSuccessHeaders()),
|
||||
"headers": mergeHeaders(standardResponseHeaders(), rateLimitSuccessHeaders(), cacheSuccessHeaders()),
|
||||
},
|
||||
"429": map[string]any{
|
||||
"description": "Too many requests",
|
||||
|
|
@ -402,6 +407,19 @@ func rateLimitSuccessHeaders() map[string]any {
|
|||
}
|
||||
}
|
||||
|
||||
// cacheSuccessHeaders documents the response header emitted on successful
|
||||
// cache hits.
|
||||
func cacheSuccessHeaders() map[string]any {
|
||||
return map[string]any{
|
||||
"X-Cache": map[string]any{
|
||||
"description": "Indicates the response was served from the in-memory cache",
|
||||
"schema": map[string]any{
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// standardResponseHeaders documents headers emitted by the response envelope
|
||||
// middleware on all responses when request IDs are enabled.
|
||||
func standardResponseHeaders() map[string]any {
|
||||
|
|
|
|||
|
|
@ -102,6 +102,11 @@ func TestSpecBuilder_Good_EmptyGroups(t *testing.T) {
|
|||
if _, ok := health504Headers["X-RateLimit-Reset"]; !ok {
|
||||
t.Fatal("expected X-RateLimit-Reset header on /health 504 response")
|
||||
}
|
||||
health200 := health["responses"].(map[string]any)["200"].(map[string]any)
|
||||
health200Headers := health200["headers"].(map[string]any)
|
||||
if _, ok := health200Headers["X-Cache"]; !ok {
|
||||
t.Fatal("expected X-Cache header on /health 200 response")
|
||||
}
|
||||
|
||||
// Verify system tag exists.
|
||||
tags := spec["tags"].([]any)
|
||||
|
|
@ -369,6 +374,9 @@ func TestSpecBuilder_Good_EnvelopeWrapping(t *testing.T) {
|
|||
if _, ok := headers["X-RateLimit-Reset"]; !ok {
|
||||
t.Fatal("expected X-RateLimit-Reset header on 200 response")
|
||||
}
|
||||
if _, ok := headers["X-Cache"]; !ok {
|
||||
t.Fatal("expected X-Cache header on 200 response")
|
||||
}
|
||||
content := resp200["content"].(map[string]any)
|
||||
appJSON := content["application/json"].(map[string]any)
|
||||
schema := appJSON["schema"].(map[string]any)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue