Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion dsl/meta.go
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,8 @@ const DefaultProtoc = expr.DefaultProtoc
// any valid JSON. Applicable to API (OpenAPI info and tag objects), Service
// (OpenAPI paths object), Method (OpenAPI path-item object), Route (OpenAPI
// operation object), Param (OpenAPI parameter object), Response (OpenAPI
// response object) and Security (OpenAPI security-scheme object). See
// response object), Security (OpenAPI security-scheme object) and types
// (OpenAPI schema object). See
// https://github.com/OAI/OpenAPI-Specification/blob/master/guidelines/EXTENSIONS.md.
//
// var _ = API("MyAPI", func() {
Expand Down
38 changes: 19 additions & 19 deletions expr/http_body_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,15 +194,7 @@ func httpRequestBody(a *HTTPEndpointExpr) *AttributeExpr {
appendSuffix(ut.Attribute().Type, suffix)

if t, ok := payload.Type.(UserType); ok {
// Remember openapi typename for example to generate friendly OpenAPI specs.
if m, ok := t.Attribute().Meta["openapi:typename"]; ok {
ut.AddMeta("openapi:typename", m...)
}

// Remember additionalProperties.
if m, ok := t.Attribute().Meta["openapi:additionalProperties"]; ok {
ut.AddMeta("openapi:additionalProperties", m...)
}
copyOpenAPITypeMeta(t, ut)
}

return &AttributeExpr{
Expand Down Expand Up @@ -335,17 +327,10 @@ func buildHTTPResponseBody(name string, attr *AttributeExpr, resp *HTTPResponseE
}

if t, ok := attr.Type.(UserType); ok {
// Remember original type name and openapi typename for example
// to generate friendly OpenAPI specs.
// Remember original type name for example to generate friendly
// OpenAPI specs.
userType.AddMeta("name:original", t.Name())
if m, ok := t.Attribute().Meta["openapi:typename"]; ok {
userType.AddMeta("openapi:typename", m...)
}

// Remember additionalProperties.
if m, ok := t.Attribute().Meta["openapi:additionalProperties"]; ok {
userType.AddMeta("openapi:additionalProperties", m...)
}
copyOpenAPITypeMeta(t, userType)
}

appendSuffix(userType.Attribute().Type, suffix)
Expand Down Expand Up @@ -402,6 +387,21 @@ func buildHTTPResponseBody(name string, attr *AttributeExpr, resp *HTTPResponseE
// 3) If the first string is a single word or camelcased, the rest of the
// strings are concatenated to form a valid upper camelcase.
// e.g. concat("myEndpoint", "streaming", "Body") => "MyEndpointStreamingBody"
// copyOpenAPITypeMeta copies the OpenAPI schema meta — type name, additional
// properties and extensions — from the original design type to the computed
// HTTP body type so the generated specs render them.
func copyOpenAPITypeMeta(from UserType, to *UserTypeExpr) {
for key, vals := range from.Attribute().Meta {
switch {
case key == "openapi:typename",
key == "openapi:additionalProperties",
strings.HasPrefix(key, "openapi:extension:"),
strings.HasPrefix(key, "swagger:extension:"):
to.AddMeta(key, vals...)
}
}
}

func concat(strs ...string) string {
if len(strs) == 1 {
return strs[0]
Expand Down
1 change: 1 addition & 0 deletions http/codegen/openapi/v3/files_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ func TestFiles(t *testing.T) {
// TestEndpoints
{"endpoint", testdata.ExtensionDSL},
{"endpoint-swagger", testdata.ExtensionSwaggerDSL},
{"type-extension", testdata.TypeExtensionDSL},
{"skip-response-body-encode-decode", testdata.SkipResponseBodyEncodeDecodeDSL},
// TestValidations
{"string", testdata.StringValidationDSL},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
{
"components": {
"schemas": {
"Notification": {
"description": "Request body for testEndpoint.",
"example": {
"id": "Doloribus qui quia."
},
"properties": {
"id": {
"example": "Quia molestias.",
"type": "string"
}
},
"type": "object",
"x-test-include": true
}
}
},
"info": {
"title": "Goa API",
"version": "0.0.1"
},
"openapi": "3.0.3",
"paths": {
"/": {
"post": {
"operationId": "testService#testEndpoint",
"requestBody": {
"content": {
"application/json": {
"example": {
"id": "Et tempora et quae."
},
"schema": {
"$ref": "#/components/schemas/Notification"
}
}
},
"description": "Request body for testEndpoint.",
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"example": {
"id": "Itaque inventore optio."
},
"schema": {
"$ref": "#/components/schemas/Notification"
}
}
},
"description": "OK response."
}
},
"summary": "testEndpoint testService",
"tags": [
"testService"
]
}
}
},
"servers": [
{
"description": "Default server for test api",
"url": "http://localhost:80"
}
],
"tags": [
{
"name": "testService"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
openapi: 3.0.3
info:
title: Goa API
version: 0.0.1
servers:
- url: http://localhost:80
description: Default server for test api
paths:
/:
post:
tags:
- testService
summary: testEndpoint testService
operationId: testService#testEndpoint
requestBody:
description: Request body for testEndpoint.
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Notification'
example:
id: Et tempora et quae.
responses:
"200":
description: OK response.
content:
application/json:
schema:
$ref: '#/components/schemas/Notification'
example:
id: Itaque inventore optio.
components:
schemas:
Notification:
description: Request body for testEndpoint.
example:
id: Doloribus qui quia.
properties:
id:
example: Quia molestias.
type: string
type: object
x-test-include: true
tags:
- name: testService
16 changes: 16 additions & 0 deletions http/codegen/testdata/openapi_dsls.go
Original file line number Diff line number Diff line change
Expand Up @@ -1163,3 +1163,19 @@ var OpenAPIInvalidVersionDSL = func() {
})
})
}

var TypeExtensionDSL = func() {
var Notification = Type("Notification", func() {
Meta("openapi:extension:x-test-include", "true")
Attribute("id", String)
})
Service("testService", func() {
Method("testEndpoint", func() {
Payload(Notification)
Result(Notification)
HTTP(func() {
POST("/")
})
})
})
}
Loading