🔥 feat: Add OpenAPI middleware#3702
Conversation
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #3702 +/- ##
==========================================
- Coverage 92.70% 91.40% -1.31%
==========================================
Files 138 141 +3
Lines 13486 14838 +1352
==========================================
+ Hits 12502 13562 +1060
- Misses 614 884 +270
- Partials 370 392 +22
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
/gemini review |
|
Warning Gemini encountered an error creating the review. You can try again by commenting |
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces a new OpenAPI middleware for auto-generating API specifications. The implementation is solid, with good test coverage and documentation. I've identified a potential improvement to prevent the middleware from documenting its own endpoint in the generated spec, which would make the output cleaner for API consumers. I also found a minor formatting issue in the documentation. Overall, this is a great feature addition.
|
nice feature, thx @gaby |
|
/gemini review |
There was a problem hiding this comment.
Pull Request Overview
This PR introduces an OpenAPI middleware that auto-generates OpenAPI 3.0 specifications from registered Fiber routes. The implementation adds per-route metadata capabilities (summary, description, tags, parameters, request/response bodies, deprecation) that can be configured either through fluent route builders or global middleware configuration.
Key changes:
- New OpenAPI middleware package with spec generation and JSON serving
- Extended
Routestruct with OpenAPI-specific metadata fields - Added fluent API methods to both
AppandGroupfor route documentation
Reviewed Changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
middleware/openapi/openapi.go |
Core middleware implementation generating OpenAPI spec from routes |
middleware/openapi/config.go |
Configuration types for middleware and operation metadata |
middleware/openapi/openapi_test.go |
Comprehensive test suite covering spec generation scenarios |
middleware/openapi/testdata/openapi.json |
Golden file fixture for JSON output validation |
router.go |
Extended Route struct with OpenAPI fields and helper types |
router_test.go |
Tests for new route metadata methods |
app.go |
Fluent API methods for documenting routes |
group.go |
Group delegation methods for route documentation |
group_test.go |
Tests for group-level route documentation |
docs/middleware/openapi.md |
User-facing middleware documentation |
docs/whats_new.md |
Release notes entry |
|
@codex review and suggest feature improvements. |
There was a problem hiding this comment.
Code Review
This pull request introduces a new OpenAPI middleware to auto-generate API specifications from routes. The implementation is comprehensive, adding new methods to App and Group for route-level documentation, and providing configuration options for global overrides. The code is well-structured and includes extensive tests.
I have two main points of feedback. The most critical one is that the current implementation incorrectly includes middleware routes (from app.Use) in the generated OpenAPI spec, which should be fixed to ensure a clean and accurate API definition. The other is a minor improvement to an error message for better debugging. Overall, this is a great feature addition.
…clusivity per OpenAPI spec Agent-Logs-Url: https://github.com/gofiber/fiber/sessions/15c9fc8c-eb8e-4dd2-a0f5-cb6a56c6c9c3 Co-authored-by: gaby <835733+gaby@users.noreply.github.com>
Audit completed and fixes applied in Fixed:
Audit notes (not bugs, architectural scope for future):
All checks pass: lint (0 issues), modernize, format, markdown, full test suite, CodeQL (0 alerts). Coverage at 90.9%. |
|
@copilot Implement automatic schema/model inference from Go structs, similar to FastAPI's auto-generation capabilities. |
… inference Add SchemaOf() function that generates OpenAPI JSON Schema from Go structs using reflection. Supports all primitive types, nested structs, embedded structs, slices, maps, time.Time, pointers, and custom openapi struct tags for description, example, format, and enum values. Includes 19 schema tests and 1 integration test. All lint checks pass. Agent-Logs-Url: https://github.com/gofiber/fiber/sessions/50af7681-fa58-4657-8390-570ea9fa0316 Co-authored-by: gaby <835733+gaby@users.noreply.github.com>
Implemented in
Usage: type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email" openapi:"format:email"`
}
// In route helpers
app.Post("/users", handler).
RequestBodyWithExample("Create user", true, openapi.SchemaOf(User{}), "", nil, nil, fiber.MIMEApplicationJSON)
// Or in Components for $ref reuse
app.Use(openapi.New(openapi.Config{
Components: map[string]any{
"schemas": map[string]any{"User": openapi.SchemaOf(User{})},
},
}))19 schema unit tests + 1 integration test added. All quality checks pass (lint, format, modernize, betteralign, markdown, full test suite, CodeQL).
Audit completed and fixes applied in Audit findings and fixes:
Schema inference (new in
All checks pass: lint (0 issues), format, modernize, betteralign, markdown (0 errors), full test suite, CodeQL (0 alerts). |
…caching Address audit gaps in the OpenAPI middleware so it produces a more complete, production-grade specification out of the box: - Security: add Config.SecuritySchemes (emitted under components.securitySchemes) and document-level Config.Security, plus a route-level Security(...) helper for per-operation requirements. - Spec completeness: add info.contact/license/termsOfService, multiple Servers (with ServerURL back-compat), top-level Tags, and ExternalDocs. - Caching: regenerate the cached spec when the registered route count changes so routes added after the first request are reflected. - Swagger UI: load the standalone preset and use StandaloneLayout by default (Authorize button), and tolerate trailing slashes on the spec/UI paths. Includes tests and docs for all of the above. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XHncVMdy1VPWCTp53PQoYG
- Introduce constants for repeated schema literals ($ref, type, format, string, object, path) in the fiber and openapi packages (goconst). - Reorder Config and openAPISpec struct fields for optimal alignment (govet fieldalignment), preserving field doc comments. - Drop the always-constant path parameter from the fetchJSON test helper (unparam). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XHncVMdy1VPWCTp53PQoYG
Replace strconv.ParseInt/ParseFloat with the gofiber/utils/v2 equivalents (utils.ParseInt, utils.ParseFloat64) in inferExampleValue, matching the repo convention of preferring Fiber utils. ParseBool stays on strconv as utils has no equivalent. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XHncVMdy1VPWCTp53PQoYG
Replace strings.TrimSpace with utils.TrimSpace in schema.go and openapi.go, and convert the case-insensitive location comparison in remapRouteParameters to utils.EqualFold (dropping the ToLower allocation). Normalization that is stored keeps utilsstrings.ToLower for consistency. strings stays for the split/cut/contains helpers that have no fiber-utils equivalent. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XHncVMdy1VPWCTp53PQoYG
schema.go (SchemaOf):
- Add cycle detection so self-referential / mutually-recursive structs no
longer stack-overflow; the cycle point emits a bare {"type":"object"}.
- Marshal []byte as {"type":"string","format":"byte"} (Go encodes it base64);
fixed-size byte arrays stay number arrays.
- Flatten embedded pointers to structs (like encoding/json); embedded-pointer
fields are not marked required since the embed may be nil.
- interface{}/any -> {} (any value); skip fields with no JSON representation
(chan, func, complex, ...) instead of emitting a meaningless {}.
- Parse openapi struct tags with a directive-aware regexp so values may
contain commas and colons.
openapi.go (generateSpec):
- Emit a unique, non-empty operationId for every operation (generated from
method+path when a route has no Name; deduped with numeric suffixes).
- Auto-generated summary uses the OpenAPI path template ({id}) instead of raw
Fiber syntax (:id<int>).
Adds tests for all of the above and updates the docs.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XHncVMdy1VPWCTp53PQoYG
…hardening Features: - Hidden() route helper (Router/App/Group/domainRouter) and Route.IsHidden() exclude a route from the generated spec; generateSpec skips hidden routes. - ResponseHeader(status, name, description, schema) documents response headers, emitted under responses.<code>.headers; RouteResponse/response carry Headers and it is cloned in copyRoute. Hardening: - GET and HEAD operations never emit a requestBody (explicit or implicit). - The cached-spec route count is now read inside the mutex, so the count compared and the spec generated are always consistent. Refactor defaultResponseDescription/defaultResponseKey shared by the response helpers. Adds tests and docs for all of the above. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XHncVMdy1VPWCTp53PQoYG
Add a dependency-free structural validator (validate_test.go) that asserts the OpenAPI 3.0/3.1 invariants the middleware must satisfy: required info, valid operation methods, path-template params declared, non-empty responses with descriptions, globally-unique operationIds, valid/unique parameters, non-empty requestBody content with no body on GET/HEAD, and security requirements that reference defined securitySchemes. Runs over a feature-exercising app for both supported OpenAPI versions as a regression guard. Test-only; no behavior change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XHncVMdy1VPWCTp53PQoYG
Break the single large example blob into one titled subsection per topic (Import, Quick start, Document metadata, Authentication, Customize the Swagger UI, Document a route, Per-operation security, Response headers, Hide a route, Behavior and defaults), each with its own code block, and split the SchemaOf example into struct/route-helper/Components blocks. Content is unchanged; markdownlint passes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XHncVMdy1VPWCTp53PQoYG
Parameter serialization: RouteParameter gains deprecated/style/explode/ allowEmptyValue/allowReserved, exposed via a new AddParameter(RouteParameter) helper (Parameter/ParameterWithExample now build on it). Metadata completeness: Server.Variables (+ ServerVariable), Tag.ExternalDocs, Config.Summary (info.summary), and operation-level OperationExternalDocs. Responses & content: per-media-type request/response bodies via RouteMediaType + RequestBodyContent/ResponseContent (different schema/example/encoding per content type), and response links via ResponseLink. Advanced 3.1: Config.Webhooks, Config.JSONSchemaDialect, and an OperationExtension helper that shallow-merges arbitrary operation fields (servers, callbacks, x-*) without clobbering generated keys. The 3.1-only document fields (summary, webhooks, jsonSchemaDialect) are emitted only for OpenAPIVersion 3.1.0. New Router methods are implemented on App and delegated by Group/domainRouter; all new Route fields are deep-cloned in copyRoute. Includes tests for every feature (extending the structural validator app) and full docs sections. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XHncVMdy1VPWCTp53PQoYG
|
Reminder to myself:
|
- Accept "3.2.0" as an OpenAPIVersion (default stays 3.1.0). - Add an ordered versionAtLeast() check; emit 3.1-era fields (summary, webhooks, jsonSchemaDialect) for 3.1 AND 3.2 (previously dropped for 3.2), and 3.2-only fields for >= 3.2. - QUERY method: routes register via app.Query() (from main); the middleware emits them as the OpenAPI `query` operation for 3.2, and skips them for 3.0/3.1 where the operation key does not exist. QUERY keeps its request body. - New typed 3.2 fields: root `$self` (Config.Self), Server.Name, and License.Identifier (SPDX, 3.1+); each gated to its supporting version. - Allow the 3.2 `querystring` parameter location in AddParameter. Tag summary/parent/kind were intentionally NOT added: the 3.2 Tag Object only defines name/description/externalDocs. Other 3.2 additions (security device flow/oauth2MetadataUrl, XML nodeType, Media Type itemSchema, additionalOperations, components.mediaTypes) are supplied via the existing raw-map Components/schemas. Adds tests (version gating, QUERY gating, querystring location), extends the structural validator to cover `query`/`querystring` and a 3.2 case, and documents all of the above. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XHncVMdy1VPWCTp53PQoYG
Add coverage_test.go exercising the internal helper edge branches that the black-box tests don't reach: uniqueOperationID fallback/suffix, schemaFrom, mediaTypesToContent/routeMediaTypeContent empties, buildRequestBody guards, shouldIncludeRequestBody, defaultResponseForMethod, buildServers (empty-URL skip, name gating, ServerURL fallback), buildComponents securityScheme merge, mergeRouteParameters (blank name, default location), remapRouteParameters (unknown path param dropped), sanitize/resolve param-name helpers, buildOpenAPIPathVariants edge cases, inferExampleValue, and SchemaOf with unsupported slice/map element types. Plus two black-box error paths (spec-marshal and swagger-options-marshal failures) via app.Test. Statement coverage 92.8% -> 98.6%. The remaining lines are unreachable defensive guards (JSON marshal/unmarshal errors on known-good structs, the swagger template execute error, resolvedSpecPath empty-path/nil-route guards, the applyOpenAPITag/convertToOpenAPIPath dead branches). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XHncVMdy1VPWCTp53PQoYG
Description
This PR introduces an OpenAPI middleware that auto-generates OpenAPI 3.0 specifications from registered Fiber routes. The middleware provides comprehensive support for documenting APIs through both fluent route methods and middleware configuration, making it easy to maintain up-to-date API documentation.
Changes introduced
OpenAPI Middleware Package: New middleware that automatically generates OpenAPI 3.0 JSON specifications from your Fiber application routes
Route Metadata Support: Extended the
Routestruct with OpenAPI-specific fields includingSummary,Description,Tags,Parameters,RequestBody,Responses,Consumes,Produces, andDeprecatedFluent API Methods: Added chainable methods to
App,Group, anddomainRouterfor documenting routes inline (e.g.,.Summary(),.Description(),.Tags(),.Parameter(),.Response(),.RequestBody())Schema References: Support for OpenAPI schema references (
$ref) and examples at the parameter, request body, and response levelsAuto-filtering: Automatically filters out Fiber's auto-generated HEAD routes (via
Route.IsAutoHead()) and middleware routes registered withUse()(viaRoute.IsMiddleware()) to avoid cluttering the spec with synthetic operationsRoute Introspection Methods: Added
IsMiddleware()andIsAutoHead()public methods onRouteto allow middleware and external consumers to distinguish middleware/auto-generated routes from user-defined routesFlexible Configuration: Per-route metadata can be provided via fluent API or global middleware config (keyed by Fiber route syntax, e.g.
GET /users/:id), with config taking precedenceExplicit Request Body Suppression: A non-nil config
RequestBodywith an emptyContentmap is treated as an explicit "no request body" override, preventing the default auto-insertion for POST/PUT/PATCH methodsGroup Support: Correctly handles grouped routes and mounted sub-apps with proper path resolution
Domain Router Support: All OpenAPI fluent methods are implemented on
domainRouter, ensuring domain-scoped routes can be documented identically to standard routesSafe Route Cloning:
copyRoute()deep-clones all OpenAPI-related fields including Tags, Parameters, Responses, and RequestBody to prevent shared backing arrays between mounted/cloned appsImmutable Route Metadata:
App.Tags()defensive-copies the incoming variadic slice before storing, preventing caller-side mutations from affecting route metadataOpenAPI Spec Validity:
buildRequestBody()omits the request body entirely when content is empty, preventing invalid OpenAPI documents with"content":nullMerge Conflict Fixes: Resolved duplicate field declarations in Route struct, handler type conversion issues, semantic conflicts in test files, and integrated parallel benchmark tests from main branch
Code Quality Improvements: Fixed all lint issues (deprecated
utils.ToLowerreplaced withutilsstrings.ToLower, 28 httpNoBody warnings, 5 whyNoLint warnings, 4 paramTypeCombine warnings, 2 hugeParam warnings), applied struct alignment optimizations (reduced Operation struct from 136 to 128 bytes, Media struct from 48 to 40 bytes), and ensured code passes all quality checks with 0 issuesSecurity Hardening:
Consumes()andProduces()now trim whitespace before validation, preventing unexpected panics from inputs like" application/json"or trailing spacesconvertToOpenAPIPath()function that properly converts Fiber route patterns to valid OpenAPI path templates by stripping type constraints (:id<int>→{id}), handling regex constraints, converting wildcards (*and+→{wildcard}), and skipping optional markers (?)appendOrReplaceParameter()to prevent potential runtime panics if code is refactoredconvertToOpenAPIPath()properly guarded with length checks to prevent index out of bounds errorsDocumentation Improvements:
Test Coverage Improvements: Comprehensive test suite with 93.1% code coverage (exceeding 90% goal)
t.Parallel()for concurrent executionmergeConfigParameters(76.9% → 92.3%),buildRequestBody(58.8% → 94.1%),schemaFrom(70.0% → 90.0%),shouldIncludeRequestBody(77.8% → 88.9%),resolvedSpecPath(70.6% → 82.4%),convertMediaContent(63.2% → 78.9%)Benchmarks: No performance impact as spec generation happens once on first request via
sync.Once. Merged 17 parallel benchmark tests from main branch to ensure thread-safety of router operations.Documentation Update: Added comprehensive documentation at
docs/middleware/openapi.mdwith examples and configuration options. Operations key format clarified to use Fiber route syntax (e.g.GET /users/:id). Added explicit caching behavior warnings. All markdown properly formatted and passing linting.Changelog/What's New: OpenAPI middleware enables automatic API documentation generation from route definitions. Default responses documented as
200 OKfor most methods,204 No ContentforDELETEandHEAD. Properly handles Fiber route constraints and wildcards in generated OpenAPI paths.Migration Guide: No migration needed - this is a new opt-in middleware
API Alignment with Express: Not applicable - OpenAPI specification is framework-agnostic
API Longevity: The middleware uses OpenAPI 3.0 standard with extensible configuration structures to accommodate future enhancements. Security hardening ensures production stability.
Examples: Documentation includes examples for basic usage, custom metadata, schema references, grouped routes, and proper middleware registration order
Type of change
Checklist
/docs/directory for Fiber's documentation.📍 Connect Copilot coding agent with Jira, Azure Boards or Linear to delegate work to Copilot in one click without leaving your project management tool.