Add OpenAPI 3.1.1 support to Goa framework#3755
Conversation
This commit upgrades the OpenAPI specification support from 3.0.3 to 3.1.1, introducing several new features and improvements while maintaining full backward compatibility with OpenAPI 2.0 (Swagger) and 3.0 specifications. Key Changes: - Upgrade OpenAPI version from 3.0.3 to 3.1.1 across all packages - Add webhook support for documenting outgoing HTTP requests - Implement JSON Schema 2020-12 dialect compatibility - Update nullable type handling to use type arrays instead of nullable keyword New Features: - Webhook DSL and expression types for defining webhook operations - Info.Summary field for providing brief API descriptions - License.Identifier field for SPDX license identifiers - Components.PathItems for reusable path item definitions - JSONSchemaDialect field in root OpenAPI object Implementation Details: - Added Webhook() DSL function for defining webhook endpoints - Created WebhookExpr and HTTPWebhookExpr expression types - Updated Schema type handling for OpenAPI 3.1 nullable support - Fixed JSON marshaling to properly emit type fields - Added comprehensive nil safety checks throughout Code Quality Improvements: - Fixed slice initialization anti-patterns - Moved state mutations from Validate to Prepare methods - Enhanced nil safety in webhook operations - Cleaned up unnecessary comments and improved code organization Testing: - Updated all golden test files for v2 and v3 packages - Verified backward compatibility with existing specifications - Validated webhook functionality with new test cases - Ensured proper JSON Schema 2020-12 dialect output The implementation maintains full backward compatibility while enabling developers to leverage the latest OpenAPI 3.1.1 features for more comprehensive API documentation.
|
Works For Me™ I used my fork to generate Webhook Documentation in the portable version of my https://sunnybox.io email api (see screenshot):
|
|
I created the tracking Issue: #3758 |
There was a problem hiding this comment.
Thank you for the PR! Adding support for OpenAPI 3.1 would be a great addition. I left a few comments below that would be good to address before we can merge this PR. Additionally:
-
We probably need to address is backwards compatibility. I don't think we can assume all Goa users can just bump up to 3.1 (there might be tools consuming the generated OpenAPI spec that might not support 3.1 yet or might behave differently with it). So we probably need to support both 3.0.3 and 3.1.1 and generate e.g. openapi31.json and .yaml.
-
It would be nice to see if we can reuse existing DSL functions instead of introducing a complete set for Webhooks. For example
Descriptioninstead ofWebhookDescription,Payloadinstead ofWebhookPayloadetc. Also the way the HTTP verb and path is set should mirror how it's done inHTTP. -
There are a few lint issues - use
makelocally to ensure the build passes.
| } | ||
|
|
||
| // validateWebhooks validates webhooks | ||
| func (svc *HTTPServiceExpr) validateWebhooks(verr *eval.ValidationErrors) { |
There was a problem hiding this comment.
Is this really needed? seems like the DSL should ensure there's a parent?
| } | ||
|
|
||
| // Prepare webhooks - map service webhooks to HTTP webhooks | ||
| for _, w := range svc.ServiceExpr.Webhooks { |
There was a problem hiding this comment.
I wonder if we really need transport agnostic webhooks? seems pretty HTTP specific by definition. Maybe we just have HTTPWebhooks (which we could just call Webhooks)
| } | ||
|
|
||
| // WebhookFor creates or returns the HTTP webhook for the given webhook expression. | ||
| func (svc *HTTPServiceExpr) WebhookFor(w *WebhookExpr) *HTTPWebhookExpr { |
| // GenerateForOpenAPIv2 indicates whether we're generating for OpenAPI v2 (Swagger) | ||
| // When true, schemas will use v2 compatible format (single example, string type) | ||
| // When false, schemas will use v3.1 format (examples array, type arrays for nullable) | ||
| GenerateForOpenAPIv2 bool |
There was a problem hiding this comment.
It would be a lot cleaner to bite the bullet and create a separate struct. Maybe the v2 and v3.1 structs can embed a common struct for most things which would implement the common behavior. Having this global variable trigger different behavior isn't great.
|
Hmm... maybe open a new branch where you lay out the foundation? I'd be happy to contribute and fully understand that the code should adhere to your standards and overall design. I'm asking myself if it makes sense to continue with this one as you have a better feel for the project etc. |
|
Also sorry that it took me so long to respond. I've been under crazy workload. |
|
No worries, that makes sense. I'll take over - thank you for the initial pass! |

This commit upgrades the OpenAPI specification support from 3.0.3 to 3.1.1, introducing several new features and improvements while maintaining full backward compatibility with OpenAPI 2.0 (Swagger) and 3.0 specifications.
Key Changes:
New Features:
Implementation Details:
Code Quality Improvements:
Testing:
The implementation maintains full backward compatibility while enabling developers to leverage the latest OpenAPI 3.1.1 features for more comprehensive API documentation.
Let me know what you think.
Issue: #3758