diff --git a/bin/configs/go-server-required.yaml b/bin/configs/go-server-chi-api-server-test.yaml similarity index 57% rename from bin/configs/go-server-required.yaml rename to bin/configs/go-server-chi-api-server-test.yaml index fd90bbbeb83..9248d16e258 100644 --- a/bin/configs/go-server-required.yaml +++ b/bin/configs/go-server-chi-api-server-test.yaml @@ -1,6 +1,6 @@ generatorName: go-server -outputDir: samples/server/petstore/go-server-required -inputSpec: modules/openapi-generator/src/test/resources/3_0/server-required.yaml +outputDir: samples/openapi3/server/petstore/go/go-petstore +inputSpec: modules/openapi-generator/src/test/resources/3_0/go-server/petstore_with_test_endpoint.yaml templateDir: modules/openapi-generator/src/main/resources/go-server additionalProperties: hideGenerationTimestamp: "true" diff --git a/bin/configs/go-server-chi-api-server.yaml b/bin/configs/go-server-chi-api-server.yaml index 16db86a3d62..b60eb9c206c 100644 --- a/bin/configs/go-server-chi-api-server.yaml +++ b/bin/configs/go-server-chi-api-server.yaml @@ -1,6 +1,6 @@ generatorName: go-server outputDir: samples/server/petstore/go-chi-server -inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml +inputSpec: modules/openapi-generator/src/test/resources/3_0/go-server/petstore.yaml templateDir: modules/openapi-generator/src/main/resources/go-server additionalProperties: hideGenerationTimestamp: "true" diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoServerCodegen.java index 867dc5280c5..97deeb58442 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoServerCodegen.java @@ -17,40 +17,19 @@ package org.openapitools.codegen.languages; -import java.io.File; -import java.util.Arrays; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - +import com.google.common.collect.Iterables; import org.apache.commons.lang3.StringUtils; -import org.openapitools.codegen.CliOption; -import org.openapitools.codegen.CodegenConstants; -import org.openapitools.codegen.CodegenModel; -import org.openapitools.codegen.CodegenOperation; -import org.openapitools.codegen.CodegenParameter; -import org.openapitools.codegen.CodegenProperty; -import org.openapitools.codegen.CodegenType; -import org.openapitools.codegen.SupportingFile; -import org.openapitools.codegen.meta.features.DocumentationFeature; -import org.openapitools.codegen.meta.features.GlobalFeature; -import org.openapitools.codegen.meta.features.ParameterFeature; -import org.openapitools.codegen.meta.features.SchemaSupportFeature; -import org.openapitools.codegen.meta.features.SecurityFeature; -import org.openapitools.codegen.meta.features.WireFormatFeature; +import org.openapitools.codegen.*; +import org.openapitools.codegen.meta.features.*; import org.openapitools.codegen.model.ModelMap; import org.openapitools.codegen.model.ModelsMap; import org.openapitools.codegen.model.OperationMap; import org.openapitools.codegen.model.OperationsMap; -import org.openapitools.codegen.utils.ModelUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.collect.Iterables; - -import io.swagger.v3.oas.models.media.ComposedSchema; -import io.swagger.v3.oas.models.media.Schema; +import java.io.File; +import java.util.*; public class GoServerCodegen extends AbstractGoCodegen { @@ -318,7 +297,7 @@ public class GoServerCodegen extends AbstractGoCodegen { List> imports = objs.getImports(); for (ModelMap m : objs.getModels()) { - imports.add(createMapping("import", "encoding/json")); +// imports.add(createMapping("import", "encoding/json")); CodegenModel model = m.getModel(); if (model.isEnum) { diff --git a/modules/openapi-generator/src/main/resources/go-server/model.mustache b/modules/openapi-generator/src/main/resources/go-server/model.mustache index 4e7f5ea0a57..f94a100a191 100644 --- a/modules/openapi-generator/src/main/resources/go-server/model.mustache +++ b/modules/openapi-generator/src/main/resources/go-server/model.mustache @@ -39,30 +39,6 @@ type {{classname}} struct { {{/vars}} }{{/isEnum}} -// UnmarshalJSON sets *m to a copy of data while respecting defaults if specified. -func (m *{{classname}}) UnmarshalJSON(data []byte) error { - {{#vars}} - {{#defaultValue}} - {{^isArray}} - {{#isBoolean}} - m.{{name}} = {{{.}}} - {{/isBoolean}} - {{#isNumeric}} - m.{{name}} = {{{.}}} - {{/isNumeric}} - {{^isBoolean}} - {{^isNumeric}} - m.{{name}} = "{{{.}}}" - {{/isNumeric}} - {{/isBoolean}} - {{/isArray}} - {{/defaultValue}} - {{/vars}} - - type Alias {{classname}} // To avoid infinite recursion - return json.Unmarshal(data, (*Alias)(m)) -} - // Assert{{classname}}Required checks if the required fields are not zero-ed func Assert{{classname}}Required(obj {{classname}}) error { {{#hasRequired}} diff --git a/modules/openapi-generator/src/main/resources/go-server/routers.mustache b/modules/openapi-generator/src/main/resources/go-server/routers.mustache index a86bb593320..166eb257f8a 100644 --- a/modules/openapi-generator/src/main/resources/go-server/routers.mustache +++ b/modules/openapi-generator/src/main/resources/go-server/routers.mustache @@ -178,28 +178,48 @@ type ParseString[T Number | string | bool] func(v string) (T, error) // parseFloat64 parses a string parameter to an float64. func parseFloat64(param string) (float64, error) { + if param == "" { + return 0, nil + } + return strconv.ParseFloat(param, 64) } // parseFloat32 parses a string parameter to an float32. func parseFloat32(param string) (float32, error) { + if param == "" { + return 0, nil + } + v, err := strconv.ParseFloat(param, 32) return float32(v), err } // parseInt64 parses a string parameter to an int64. func parseInt64(param string) (int64, error) { + if param == "" { + return 0, nil + } + return strconv.ParseInt(param, 10, 64) } // parseInt32 parses a string parameter to an int32. func parseInt32(param string) (int32, error) { + if param == "" { + return 0, nil + } + val, err := strconv.ParseInt(param, 10, 32) return int32(val), err } // parseBool parses a string parameter to an bool. func parseBool(param string) (bool, error) { + if param == "" { + return false, nil + } + return strconv.ParseBool(param) } diff --git a/modules/openapi-generator/src/test/resources/3_0/go-server/petstore.yaml b/modules/openapi-generator/src/test/resources/3_0/go-server/petstore.yaml index b004e6e04e1..fce2c52cbde 100644 --- a/modules/openapi-generator/src/test/resources/3_0/go-server/petstore.yaml +++ b/modules/openapi-generator/src/test/resources/3_0/go-server/petstore.yaml @@ -617,9 +617,41 @@ components: name: api_key in: header schemas: + OrderInfo: + title: Pet Order Info + description: An order info for a pets from the pet store + type: object + properties: + petId: + type: integer + format: int64 + quantity: + type: integer + format: int32 + shipDate: + type: string + format: date-time + xml: + name: OrderInfo + SpecialInfo: + title: Pet Order Info + description: An order info for a pets from the pet store + discriminator: + propertyName: type + type: object + properties: + promotion: + type: boolean + type: + type: string + xml: + name: OrderInfo Order: title: Pet Order description: An order for a pets from the pet store + allOf: + - $ref: '#/components/schemas/OrderInfo' + - $ref: '#/components/schemas/SpecialInfo' type: object properties: id: @@ -644,12 +676,18 @@ components: complete: type: boolean default: false + comment: + type: string + nullable: true xml: name: Order + required: + - comment Category: title: Pet category description: A category for a pet type: object + nullable: true properties: id: type: integer @@ -679,12 +717,45 @@ components: type: string phone: type: string + nullable: true userStatus: type: integer format: int32 description: User Status + deepSliceModel: + nullable: true + type: array + description: An array 1-deep. + items: + type: array + description: An array 2-deep. + items: + type: array + description: An array 3-deep. + items: + $ref: '#/components/schemas/Tag' + deepSliceMap: + type: array + description: An array 1-deep. + items: + type: array + description: An array 2-deep. + items: + title: an Object + type: object + description: An array 3-deep. + properties: + tag: + $ref: '#/components/schemas/Tag' + Pet: + type: array + description: An array of pet. + items: + $ref: '#/components/schemas/Pet' xml: name: User + required: + - deepSliceModel Tag: title: Pet Tag description: A tag for a pet @@ -714,6 +785,7 @@ components: type: string example: doggie photoUrls: + nullable: true type: array xml: name: photoUrl @@ -721,6 +793,7 @@ components: items: type: string tags: + nullable: true type: array xml: name: tag diff --git a/modules/openapi-generator/src/test/resources/3_0/server-required.yaml b/modules/openapi-generator/src/test/resources/3_0/go-server/petstore_with_test_endpoint.yaml similarity index 79% rename from modules/openapi-generator/src/test/resources/3_0/server-required.yaml rename to modules/openapi-generator/src/test/resources/3_0/go-server/petstore_with_test_endpoint.yaml index 33dd9ce64b3..c91ce4165a8 100644 --- a/modules/openapi-generator/src/test/resources/3_0/server-required.yaml +++ b/modules/openapi-generator/src/test/resources/3_0/go-server/petstore_with_test_endpoint.yaml @@ -1,6 +1,6 @@ openapi: 3.0.0 servers: - - url: "http://petstore.swagger.io/v2" + - url: 'http://petstore.swagger.io/v2' info: description: >- This is a sample server Petstore server. For this sample, you can use the api key @@ -9,7 +9,7 @@ info: title: OpenAPI Petstore license: name: Apache-2.0 - url: "https://www.apache.org/licenses/LICENSE-2.0.html" + url: 'https://www.apache.org/licenses/LICENSE-2.0.html' tags: - name: pet description: Everything about your Pets @@ -23,54 +23,57 @@ paths: tags: - pet summary: Add a new pet to the store - description: "" + description: '' operationId: addPet responses: - "200": + '200': description: successful operation content: application/xml: schema: - $ref: "#/components/schemas/Pet" + $ref: '#/components/schemas/Pet' application/json: schema: - $ref: "#/components/schemas/Pet" - "405": + $ref: '#/components/schemas/Pet' + '405': description: Invalid input security: - petstore_auth: - - "write:pets" - - "read:pets" + - 'write:pets' + - 'read:pets' requestBody: - $ref: "#/components/requestBodies/Pet" + $ref: '#/components/requestBodies/Pet' put: tags: - pet summary: Update an existing pet - description: "" + description: '' operationId: updatePet + externalDocs: + url: "http://petstore.swagger.io/v2/doc/updatePet" + description: "API documentation for the updatePet operation" responses: - "200": + '200': description: successful operation content: application/xml: schema: - $ref: "#/components/schemas/Pet" + $ref: '#/components/schemas/Pet' application/json: schema: - $ref: "#/components/schemas/Pet" - "400": + $ref: '#/components/schemas/Pet' + '400': description: Invalid ID supplied - "404": + '404': description: Pet not found - "405": + '405': description: Validation exception security: - petstore_auth: - - "write:pets" - - "read:pets" + - 'write:pets' + - 'read:pets' requestBody: - $ref: "#/components/requestBodies/Pet" + $ref: '#/components/requestBodies/Pet' /pet/findByStatus: get: tags: @@ -85,6 +88,7 @@ paths: required: true style: form explode: false + deprecated: true schema: type: array items: @@ -95,24 +99,24 @@ paths: - sold default: available responses: - "200": + '200': description: successful operation content: application/xml: schema: type: array items: - $ref: "#/components/schemas/Pet" + $ref: '#/components/schemas/Pet' application/json: schema: type: array items: - $ref: "#/components/schemas/Pet" - "400": + $ref: '#/components/schemas/Pet' + '400': description: Invalid status value security: - petstore_auth: - - "read:pets" + - 'read:pets' /pet/findByTags: get: tags: @@ -134,26 +138,26 @@ paths: items: type: string responses: - "200": + '200': description: successful operation content: application/xml: schema: type: array items: - $ref: "#/components/schemas/Pet" + $ref: '#/components/schemas/Pet' application/json: schema: type: array items: - $ref: "#/components/schemas/Pet" - "400": + $ref: '#/components/schemas/Pet' + '400': description: Invalid tag value security: - petstore_auth: - - "read:pets" + - 'read:pets' deprecated: true - "/pet/{petId}": + '/pet/{petId}': get: tags: - pet @@ -169,18 +173,18 @@ paths: type: integer format: int64 responses: - "200": + '200': description: successful operation content: application/xml: schema: - $ref: "#/components/schemas/Pet" + $ref: '#/components/schemas/Pet' application/json: schema: - $ref: "#/components/schemas/Pet" - "400": + $ref: '#/components/schemas/Pet' + '400': description: Invalid ID supplied - "404": + '404': description: Pet not found security: - api_key: [] @@ -188,7 +192,7 @@ paths: tags: - pet summary: Updates a pet in the store with form data - description: "" + description: '' operationId: updatePetWithForm parameters: - name: petId @@ -199,12 +203,12 @@ paths: type: integer format: int64 responses: - "405": + '405': description: Invalid input security: - petstore_auth: - - "write:pets" - - "read:pets" + - 'write:pets' + - 'read:pets' requestBody: content: application/x-www-form-urlencoded: @@ -221,7 +225,7 @@ paths: tags: - pet summary: Deletes a pet - description: "" + description: '' operationId: deletePet parameters: - name: api_key @@ -237,18 +241,18 @@ paths: type: integer format: int64 responses: - "400": + '400': description: Invalid pet value security: - petstore_auth: - - "write:pets" - - "read:pets" - "/pet/{petId}/uploadImage": + - 'write:pets' + - 'read:pets' + '/pet/{petId}/uploadImage': post: tags: - pet summary: uploads an image - description: "" + description: '' operationId: uploadFile parameters: - name: petId @@ -259,16 +263,16 @@ paths: type: integer format: int64 responses: - "200": + '200': description: successful operation content: application/json: schema: - $ref: "#/components/schemas/ApiResponse" + $ref: '#/components/schemas/ApiResponse' security: - petstore_auth: - - "write:pets" - - "read:pets" + - 'write:pets' + - 'read:pets' requestBody: content: multipart/form-data: @@ -290,7 +294,7 @@ paths: description: Returns a map of status codes to quantities operationId: getInventory responses: - "200": + '200': description: successful operation content: application/json: @@ -306,28 +310,28 @@ paths: tags: - store summary: Place an order for a pet - description: "" + description: '' operationId: placeOrder responses: - "200": + '200': description: successful operation content: application/xml: schema: - $ref: "#/components/schemas/Order" + $ref: '#/components/schemas/Order' application/json: schema: - $ref: "#/components/schemas/Order" - "400": + $ref: '#/components/schemas/Order' + '400': description: Invalid Order requestBody: content: application/json: schema: - $ref: "#/components/schemas/Order" + $ref: '#/components/schemas/Order' description: order placed for purchasing the pet required: true - "/store/order/{orderId}": + '/store/order/{orderId}': get: tags: - store @@ -347,18 +351,18 @@ paths: minimum: 1 maximum: 5 responses: - "200": + '200': description: successful operation content: application/xml: schema: - $ref: "#/components/schemas/Order" + $ref: '#/components/schemas/Order' application/json: schema: - $ref: "#/components/schemas/Order" - "400": + $ref: '#/components/schemas/Order' + '400': description: Invalid ID supplied - "404": + '404': description: Order not found delete: tags: @@ -376,9 +380,9 @@ paths: schema: type: string responses: - "400": + '400': description: Invalid ID supplied - "404": + '404': description: Order not found /user: post: @@ -396,7 +400,7 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/User" + $ref: '#/components/schemas/User' description: Created user object required: true /user/createWithArray: @@ -404,7 +408,7 @@ paths: tags: - user summary: Creates list of users with given input array - description: "" + description: '' operationId: createUsersWithArrayInput responses: default: @@ -412,13 +416,13 @@ paths: security: - api_key: [] requestBody: - $ref: "#/components/requestBodies/UserArray" + $ref: '#/components/requestBodies/UserArray' /user/createWithList: post: tags: - user summary: Creates list of users with given input array - description: "" + description: '' operationId: createUsersWithListInput responses: default: @@ -426,13 +430,13 @@ paths: security: - api_key: [] requestBody: - $ref: "#/components/requestBodies/UserArray" + $ref: '#/components/requestBodies/UserArray' /user/login: get: tags: - user summary: Logs user into the system - description: "" + description: '' operationId: loginUser parameters: - name: username @@ -448,8 +452,36 @@ paths: required: true schema: type: string + - name: int32_test + in: query + description: The password for login in clear text + schema: + type: integer + format: int32 + - name: int64_test + in: query + description: The password for login in clear text + schema: + type: integer + format: int64 + - name: float32_test + in: query + description: The password for login in clear text + schema: + type: number + - name: float64_test + in: query + description: The password for login in clear text + schema: + type: number + format: double + - name: boolean_test + in: query + description: The password for login in clear text + schema: + type: boolean responses: - "200": + '200': description: successful operation headers: Set-Cookie: @@ -476,26 +508,26 @@ paths: application/json: schema: type: string - "400": + '400': description: Invalid username/password supplied /user/logout: get: tags: - user summary: Logs out current logged in user session - description: "" + description: '' operationId: logoutUser responses: default: description: successful operation security: - api_key: [] - "/user/{username}": + '/user/{username}': get: tags: - user summary: Get user by user name - description: "" + description: '' operationId: getUserByName parameters: - name: username @@ -505,18 +537,18 @@ paths: schema: type: string responses: - "200": + '200': description: successful operation content: application/xml: schema: - $ref: "#/components/schemas/User" + $ref: '#/components/schemas/User' application/json: schema: - $ref: "#/components/schemas/User" - "400": + $ref: '#/components/schemas/User' + '400': description: Invalid username supplied - "404": + '404': description: User not found put: tags: @@ -532,9 +564,9 @@ paths: schema: type: string responses: - "400": + '400': description: Invalid user supplied - "404": + '404': description: User not found security: - api_key: [] @@ -542,7 +574,7 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/User" + $ref: '#/components/schemas/User' description: Updated user object required: true delete: @@ -558,16 +590,21 @@ paths: required: true schema: type: string + - name: boolean_test # to ensure boolean query parameter won't cause compilation errors + in: query + description: boolean query parameter + schema: + type: boolean responses: - "400": + '400': description: Invalid username supplied - "404": + '404': description: User not found security: - api_key: [] externalDocs: description: Find out more about Swagger - url: "http://swagger.io" + url: 'http://swagger.io' components: requestBodies: UserArray: @@ -576,17 +613,17 @@ components: schema: type: array items: - $ref: "#/components/schemas/User" + $ref: '#/components/schemas/User' description: List of user object required: true Pet: content: application/json: schema: - $ref: "#/components/schemas/Pet" + $ref: '#/components/schemas/Pet' application/xml: schema: - $ref: "#/components/schemas/Pet" + $ref: '#/components/schemas/Pet' description: Pet object that needs to be added to the store required: true securitySchemes: @@ -594,10 +631,10 @@ components: type: oauth2 flows: implicit: - authorizationUrl: "http://petstore.swagger.io/api/oauth/dialog" + authorizationUrl: 'http://petstore.swagger.io/api/oauth/dialog' scopes: - "write:pets": modify pets in your account - "read:pets": read your pets + 'write:pets': modify pets in your account + 'read:pets': read your pets api_key: type: apiKey name: api_key @@ -628,8 +665,12 @@ components: properties: promotion: type: boolean + requireTest: + type: string type: type: string + required: + - requireTest xml: name: OrderInfo Order: @@ -643,6 +684,15 @@ components: id: type: integer format: int64 + petId: + type: integer + format: int64 + quantity: + type: integer + format: int32 + shipDate: + type: string + format: date-time status: type: string description: Order Status @@ -710,7 +760,7 @@ components: type: array description: An array 3-deep. items: - $ref: "#/components/schemas/Tag" + $ref: '#/components/schemas/Tag' deepSliceMap: type: array description: An array 1-deep. @@ -723,12 +773,12 @@ components: description: An array 3-deep. properties: tag: - $ref: "#/components/schemas/Tag" + $ref: '#/components/schemas/Tag' Pet: type: array description: An array of pet. items: - $ref: "#/components/schemas/Pet" + $ref: '#/components/schemas/Pet' xml: name: User required: @@ -757,7 +807,7 @@ components: type: integer format: int64 category: - $ref: "#/components/schemas/Category" + $ref: '#/components/schemas/Category' name: type: string example: doggie @@ -776,10 +826,11 @@ components: name: tag wrapped: true items: - $ref: "#/components/schemas/Tag" + $ref: '#/components/schemas/Tag' status: type: string description: pet status in the store + deprecated: true enum: - available - pending diff --git a/samples/openapi3/server/petstore/go/.gitignore b/samples/openapi3/server/petstore/go/.gitignore new file mode 100644 index 00000000000..e6837a95a1e --- /dev/null +++ b/samples/openapi3/server/petstore/go/.gitignore @@ -0,0 +1,6 @@ +# Editor directories and files +.vscode/ +__debug_bin + +# Dependency directories (remove the comment below to include it) +vendor/ diff --git a/samples/openapi3/server/petstore/go/api_store_test.go b/samples/openapi3/server/petstore/go/api_store_test.go new file mode 100644 index 00000000000..ed6ab3dbbe3 --- /dev/null +++ b/samples/openapi3/server/petstore/go/api_store_test.go @@ -0,0 +1,125 @@ +package main + +import ( + "context" + "io" + "net/http" + "net/http/httptest" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + petstoreserver "go-petstore/go" +) + +type StoreAPITestService struct { + petstoreserver.StoreAPIServicer + placeOrder func(order petstoreserver.Order) (petstoreserver.ImplResponse, error) +} + +// PlaceOrder - Place an order for a pet +func (s *StoreAPITestService) PlaceOrder(ctx context.Context, order petstoreserver.Order) (petstoreserver.ImplResponse, error) { + return s.placeOrder(order) +} + +// TestPlaceOrderOK tests PlaceOrder operation. This operation contains Order which has an +// embedding struct that will be tested as well. +func TestPlaceOrderOK(t *testing.T) { + const ( + payload = `{ + "petId": 6, + "quantity": 1, + "comment": "comment", + "id": 0, + "shipDate": "2000-01-23T04:56:07.000+00:00", + "complete": false, + "status": "placed", + "RequireTest": "required" + }` + status = http.StatusOK + ) + + bodyReader := strings.NewReader(payload) + req := httptest.NewRequest(http.MethodPost, "/v2/store/order", bodyReader) + w := httptest.NewRecorder() + + // Create the service and inject the logic + service := &StoreAPITestService{} + service.placeOrder = func(order petstoreserver.Order) (petstoreserver.ImplResponse, error) { + comment := "comment" + assert.Equal(t, int64(6), order.PetId) + assert.Equal(t, int32(1), order.Quantity) + assert.Equal(t, &comment, order.Comment) + assert.Equal(t, int64(0), order.Id) + // assert.Equal(t, time.Time, order.ShipDate) // TODO: Fix datetime test + assert.False(t, order.Complete) + assert.Equal(t, "placed", order.Status) + assert.Equal(t, "required", order.RequireTest) + + return petstoreserver.Response(status, nil), nil + } + + // Create the controller with the service + router := petstoreserver.NewStoreAPIController(service) + controller, ok := router.(*petstoreserver.StoreAPIController) + require.True(t, ok) + + // Call the method of controller we are testing + controller.PlaceOrder(w, req) + + res := w.Result() + assert.Equal(t, status, res.StatusCode) + defer res.Body.Close() + + // Check the response + data, err := io.ReadAll(res.Body) + require.NoError(t, err) + assert.Empty(t, data) +} + +// TestPlaceOrderFailEmbeddedRequired tests PlaceOrder operation. This operation contains Order which has an +// embedding struct that will be tested as well. +func TestPlaceOrderFailEmbeddedRequired(t *testing.T) { + const ( + payload = `{ + "petId": 6, + "quantity": 1, + "comment": "comment", + "id": 0, + "shipDate": "2000-01-23T04:56:07.000+00:00", + "complete": false, + "status": "placed" + }` + status = http.StatusUnprocessableEntity + ) + + bodyReader := strings.NewReader(payload) + req := httptest.NewRequest(http.MethodPost, "/v2/store/order", bodyReader) + w := httptest.NewRecorder() + + // Create the service and inject the logic + service := &StoreAPITestService{} + service.placeOrder = func(order petstoreserver.Order) (petstoreserver.ImplResponse, error) { + assert.FailNow(t, "should not reach this") + + return petstoreserver.Response(status, nil), nil + } + + // Create the controller with the service + router := petstoreserver.NewStoreAPIController(service) + controller, ok := router.(*petstoreserver.StoreAPIController) + require.True(t, ok) + + // Call the method of controller we are testing + controller.PlaceOrder(w, req) + + res := w.Result() + assert.Equal(t, status, res.StatusCode) + defer res.Body.Close() + + // Check the response + data, err := io.ReadAll(res.Body) + require.NoError(t, err) + assert.Equal(t, "\"required field 'requireTest' is zero value.\"\n", string(data)) +} diff --git a/samples/openapi3/server/petstore/go/api_user_test.go b/samples/openapi3/server/petstore/go/api_user_test.go new file mode 100644 index 00000000000..ecf2fb18fc9 --- /dev/null +++ b/samples/openapi3/server/petstore/go/api_user_test.go @@ -0,0 +1,403 @@ +package main + +import ( + "context" + "io" + "net/http" + "net/http/httptest" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + petstoreserver "go-petstore/go" +) + +type UserAPITestService struct { + petstoreserver.UserAPIServicer + createUser func(user petstoreserver.User) (petstoreserver.ImplResponse, error) + loginUser func(username string, password string, int32Test int32, int64Test int64, float32Test float32, + float64Test float64, booleanTest bool) (petstoreserver.ImplResponse, error) +} + +// CreateUser - Create user +func (s *UserAPITestService) CreateUser(ctx context.Context, user petstoreserver.User) (petstoreserver.ImplResponse, error) { + return s.createUser(user) +} + +// LoginUser - Logs user into the system +func (s *UserAPITestService) LoginUser(ctx context.Context, username string, password string, int32Test int32, + int64Test int64, float32Test float32, float64Test float64, booleanTest bool) (petstoreserver.ImplResponse, error) { + return s.loginUser(username, password, int32Test, int64Test, float32Test, float64Test, booleanTest) +} + +func TestCreateUserOK(t *testing.T) { + const ( + payload = `{ + "firstName": "firstName", + "lastName": "lastName", + "password": "password", + "userStatus": 6, + "phone": "phone", + "deepSliceModel": [ + [ + [ + { + "name": "name", + "id": 1 + } + ] + ] + ], + "id": 0, + "deepSliceMap": [ + [ + { + "tag": { + "name": "name", + "id": 1 + }, + "Pet": [ + { + "photoUrls": [ + "photoUrls", + "photoUrls" + ], + "name": "doggie", + "id": 0, + "category": { + "name": "name", + "id": 6 + }, + "tags": [ + { + "name": "name", + "id": 1 + } + ], + "status": "available" + } + ] + } + ] + ], + "email": "email", + "username": "username" + }` + status = http.StatusOK + ) + + bodyReader := strings.NewReader(payload) + req := httptest.NewRequest(http.MethodPost, "/v2/user", bodyReader) + w := httptest.NewRecorder() + + // Create the service and inject the logic + service := &UserAPITestService{} + service.createUser = func(user petstoreserver.User) (petstoreserver.ImplResponse, error) { + phone := "phone" + assert.Equal(t, "firstName", user.FirstName) + assert.Equal(t, "lastName", user.LastName) + assert.Equal(t, "password", user.Password) + assert.Equal(t, int32(6), user.UserStatus) + assert.Equal(t, &phone, user.Phone) + assert.Equal(t, &[][][]petstoreserver.Tag{ + { + { + {Id: 1, Name: "name"}, + }, + }, + }, user.DeepSliceModel) + assert.Equal(t, int64(0), user.Id) + assert.Equal(t, "email", user.Email) + assert.Equal(t, "username", user.Username) + + return petstoreserver.Response(status, nil), nil + } + + // Create the controller with the service + router := petstoreserver.NewUserAPIController(service) + controller, ok := router.(*petstoreserver.UserAPIController) + require.True(t, ok) + + // Call the method of controller we are testing + controller.CreateUser(w, req) + + res := w.Result() + assert.Equal(t, status, res.StatusCode) + defer res.Body.Close() + + // Check the response + data, err := io.ReadAll(res.Body) + require.NoError(t, err) + assert.Empty(t, data) +} + +func TestCreateUserOKNullablePhone(t *testing.T) { + const ( + payload = `{ + "firstName": "firstName", + "lastName": "lastName", + "password": "password", + "userStatus": 6, + "deepSliceModel": [ + [ + [ + { + "name": "name", + "id": 1 + } + ] + ] + ], + "id": 0, + "deepSliceMap": [ + [ + { + "tag": { + "name": "name", + "id": 1 + }, + "Pet": [ + { + "photoUrls": [ + "photoUrls", + "photoUrls" + ], + "name": "doggie", + "id": 0, + "category": { + "name": "name", + "id": 6 + }, + "tags": [ + { + "name": "name", + "id": 1 + } + ], + "status": "available" + } + ] + } + ] + ], + "email": "email", + "username": "username" + }` + status = http.StatusOK + ) + + bodyReader := strings.NewReader(payload) + req := httptest.NewRequest(http.MethodPost, "/v2/user", bodyReader) + w := httptest.NewRecorder() + + // Create the service and inject the logic + service := &UserAPITestService{} + service.createUser = func(user petstoreserver.User) (petstoreserver.ImplResponse, error) { + assert.Equal(t, "firstName", user.FirstName) + assert.Equal(t, "lastName", user.LastName) + assert.Equal(t, "password", user.Password) + assert.Equal(t, int32(6), user.UserStatus) + assert.Nil(t, user.Phone) + assert.Equal(t, &[][][]petstoreserver.Tag{ + { + { + {Id: 1, Name: "name"}, + }, + }, + }, user.DeepSliceModel) + assert.Equal(t, int64(0), user.Id) + assert.Equal(t, "email", user.Email) + assert.Equal(t, "username", user.Username) + + return petstoreserver.Response(status, nil), nil + } + + // Create the controller with the service + router := petstoreserver.NewUserAPIController(service) + controller, ok := router.(*petstoreserver.UserAPIController) + require.True(t, ok) + + // Call the method of controller we are testing + controller.CreateUser(w, req) + + res := w.Result() + assert.Equal(t, status, res.StatusCode) + defer res.Body.Close() + + // Check the response + data, err := io.ReadAll(res.Body) + require.NoError(t, err) + assert.Empty(t, data) +} + +func TestCreateUserFailDeepSliceModelRequired(t *testing.T) { + const ( + payload = `{ + "firstName": "firstName", + "lastName": "lastName", + "password": "password", + "userStatus": 6, + "phone": "phone", + "id": 0, + "email": "email", + "username": "username" + }` + status = http.StatusUnprocessableEntity + ) + + bodyReader := strings.NewReader(payload) + req := httptest.NewRequest(http.MethodPost, "/v2/user", bodyReader) + w := httptest.NewRecorder() + + // Create the service and inject the logic + service := &UserAPITestService{} + service.createUser = func(user petstoreserver.User) (petstoreserver.ImplResponse, error) { + assert.FailNow(t, "should not reach this") + return petstoreserver.Response(status, nil), nil + } + + // Create the controller with the service + router := petstoreserver.NewUserAPIController(service) + controller, ok := router.(*petstoreserver.UserAPIController) + require.True(t, ok) + + // Call the method of controller we are testing + controller.CreateUser(w, req) + + res := w.Result() + assert.Equal(t, status, res.StatusCode) + defer res.Body.Close() + + // Check the response + data, err := io.ReadAll(res.Body) + require.NoError(t, err) + assert.Equal(t, "\"required field 'deepSliceModel' is zero value.\"\n", string(data)) +} + +// func TestCreateUserFailDeepSliceModelEmptyRecursive(t *testing.T) { +// const ( +// payload = `{ +// "firstName": "firstName", +// "lastName": "lastName", +// "password": "password", +// "userStatus": 6, +// "phone": "phone", +// "deepSliceModel": [ +// [ +// ] +// ], +// "id": 0, +// "email": "email", +// "username": "username" +// }` +// status = http.StatusUnprocessableEntity +// ) + +// bodyReader := strings.NewReader(payload) +// req := httptest.NewRequest(http.MethodPost, "/v2/user", bodyReader) +// w := httptest.NewRecorder() + +// // Create the service and inject the logic +// service := &UserAPITestService{} +// service.createUser = func(user petstoreserver.User) (petstoreserver.ImplResponse, error) { +// assert.FailNow(t, "should not reach this") +// return petstoreserver.Response(status, nil), nil +// } + +// // Create the controller with the service +// router := petstoreserver.NewUserAPIController(service) +// controller, ok := router.(*petstoreserver.UserAPIController) +// require.True(t, ok) + +// // Call the method of controller we are testing +// controller.CreateUser(w, req) + +// res := w.Result() +// assert.Equal(t, status, res.StatusCode) +// defer res.Body.Close() + +// // Check the response +// data, err := io.ReadAll(res.Body) +// require.NoError(t, err) +// assert.Equal(t, "\"required field 'deepSliceModel' is zero value.\"\n", string(data)) +// } + +func TestLoginUserOK(t *testing.T) { + const ( + status = http.StatusOK + ) + + req := httptest.NewRequest(http.MethodPost, "/user/login?username=test&int32_test=1&int64_test=2&float32_test=1.1&float64_test=1.2&boolean_test=true", nil) + w := httptest.NewRecorder() + + // Create the service and inject the logic + service := &UserAPITestService{} + service.loginUser = func(username, password string, int32Test int32, int64Test int64, float32Test float32, float64Test float64, booleanTest bool) (petstoreserver.ImplResponse, error) { + assert.Equal(t, "test", username) + assert.Equal(t, int32(1), int32Test) + assert.Equal(t, int64(2), int64Test) + assert.Equal(t, float32(1.1), float32Test) + assert.Equal(t, float64(1.2), float64Test) + assert.True(t, booleanTest) + + return petstoreserver.Response(status, nil), nil + } + + // Create the controller with the service + router := petstoreserver.NewUserAPIController(service) + controller, ok := router.(*petstoreserver.UserAPIController) + require.True(t, ok) + + // Call the method of controller we are testing + controller.LoginUser(w, req) + + res := w.Result() + assert.Equal(t, status, res.StatusCode) + defer res.Body.Close() + + // Check the response + data, err := io.ReadAll(res.Body) + require.NoError(t, err) + assert.Empty(t, data) +} + +func TestLoginUserOKOptional(t *testing.T) { + const ( + status = http.StatusOK + ) + + req := httptest.NewRequest(http.MethodPost, "/user/login?username=test", nil) + w := httptest.NewRecorder() + + // Create the service and inject the logic + service := &UserAPITestService{} + service.loginUser = func(username, password string, int32Test int32, int64Test int64, float32Test float32, + float64Test float64, booleanTest bool) (petstoreserver.ImplResponse, error) { + assert.Equal(t, "test", username) + assert.Zero(t, int32Test) + assert.Zero(t, int64Test) + assert.Zero(t, float32Test) + assert.Zero(t, float64Test) + assert.Zero(t, booleanTest) + + return petstoreserver.Response(status, nil), nil + } + + // Create the controller with the service + router := petstoreserver.NewUserAPIController(service) + controller, ok := router.(*petstoreserver.UserAPIController) + require.True(t, ok) + + // Call the method of controller we are testing + controller.LoginUser(w, req) + + res := w.Result() + assert.Equal(t, status, res.StatusCode) + defer res.Body.Close() + + // Check the response + data, err := io.ReadAll(res.Body) + require.NoError(t, err) + assert.Empty(t, data) +} diff --git a/samples/openapi3/server/petstore/go/go-petstore/.openapi-generator-ignore b/samples/openapi3/server/petstore/go/go-petstore/.openapi-generator-ignore new file mode 100644 index 00000000000..7484ee590a3 --- /dev/null +++ b/samples/openapi3/server/petstore/go/go-petstore/.openapi-generator-ignore @@ -0,0 +1,23 @@ +# OpenAPI Generator Ignore +# Generated by openapi-generator https://github.com/openapitools/openapi-generator + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md diff --git a/samples/openapi3/server/petstore/go/go-petstore/.openapi-generator/FILES b/samples/openapi3/server/petstore/go/go-petstore/.openapi-generator/FILES new file mode 100644 index 00000000000..4c3a2a3a7c7 --- /dev/null +++ b/samples/openapi3/server/petstore/go/go-petstore/.openapi-generator/FILES @@ -0,0 +1,26 @@ +Dockerfile +README.md +api/openapi.yaml +go.mod +go/api.go +go/api_pet.go +go/api_pet_service.go +go/api_store.go +go/api_store_service.go +go/api_user.go +go/api_user_service.go +go/error.go +go/helpers.go +go/impl.go +go/logger.go +go/model_an_object.go +go/model_api_response.go +go/model_category.go +go/model_order.go +go/model_order_info.go +go/model_pet.go +go/model_special_info.go +go/model_tag.go +go/model_user.go +go/routers.go +main.go diff --git a/samples/openapi3/server/petstore/go/go-petstore/.openapi-generator/VERSION b/samples/openapi3/server/petstore/go/go-petstore/.openapi-generator/VERSION new file mode 100644 index 00000000000..757e6740040 --- /dev/null +++ b/samples/openapi3/server/petstore/go/go-petstore/.openapi-generator/VERSION @@ -0,0 +1 @@ +7.0.0-SNAPSHOT \ No newline at end of file diff --git a/samples/openapi3/server/petstore/go/go-petstore/Dockerfile b/samples/openapi3/server/petstore/go/go-petstore/Dockerfile new file mode 100644 index 00000000000..2a71bb77629 --- /dev/null +++ b/samples/openapi3/server/petstore/go/go-petstore/Dockerfile @@ -0,0 +1,15 @@ +FROM golang:1.19 AS build +WORKDIR /go/src +COPY go ./go +COPY main.go . +COPY go.sum . +COPY go.mod . + +ENV CGO_ENABLED=0 + +RUN go build -o petstoreserver . + +FROM scratch AS runtime +COPY --from=build /go/src/petstoreserver ./ +EXPOSE 8080/tcp +ENTRYPOINT ["./petstoreserver"] diff --git a/samples/openapi3/server/petstore/go/go-petstore/README.md b/samples/openapi3/server/petstore/go/go-petstore/README.md new file mode 100644 index 00000000000..7a0c3bb1119 --- /dev/null +++ b/samples/openapi3/server/petstore/go/go-petstore/README.md @@ -0,0 +1,33 @@ +# Go API Server for petstoreserver + +This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + +## Overview +This server was generated by the [openapi-generator] +(https://openapi-generator.tech) project. +By using the [OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate a server stub. +- + +To see how to make this your own, look here: + +[README](https://openapi-generator.tech) + +- API version: 1.0.0 + + +### Running the server +To run the server, follow these simple steps: + +``` +go run main.go +``` + +To run the server in a docker container +``` +docker build --network=host -t petstoreserver . +``` + +Once image is built use +``` +docker run --rm -it petstoreserver +``` diff --git a/samples/openapi3/server/petstore/go/go-petstore/api/openapi.yaml b/samples/openapi3/server/petstore/go/go-petstore/api/openapi.yaml new file mode 100644 index 00000000000..0f32c07b983 --- /dev/null +++ b/samples/openapi3/server/petstore/go/go-petstore/api/openapi.yaml @@ -0,0 +1,1121 @@ +openapi: 3.0.0 +info: + description: "This is a sample server Petstore server. For this sample, you can\ + \ use the api key `special-key` to test the authorization filters." + license: + name: Apache-2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html + title: OpenAPI Petstore + version: 1.0.0 +externalDocs: + description: Find out more about Swagger + url: http://swagger.io +servers: +- url: http://petstore.swagger.io/v2 +tags: +- description: Everything about your Pets + name: pet +- description: Access to Petstore orders + name: store +- description: Operations about user + name: user +paths: + /pet: + post: + description: "" + operationId: addPet + requestBody: + $ref: '#/components/requestBodies/Pet' + responses: + "200": + content: + application/xml: + schema: + $ref: '#/components/schemas/Pet' + application/json: + schema: + $ref: '#/components/schemas/Pet' + description: successful operation + "405": + description: Invalid input + security: + - petstore_auth: + - write:pets + - read:pets + summary: Add a new pet to the store + tags: + - pet + put: + description: "" + externalDocs: + description: API documentation for the updatePet operation + url: http://petstore.swagger.io/v2/doc/updatePet + operationId: updatePet + requestBody: + $ref: '#/components/requestBodies/Pet' + responses: + "200": + content: + application/xml: + schema: + $ref: '#/components/schemas/Pet' + application/json: + schema: + $ref: '#/components/schemas/Pet' + description: successful operation + "400": + description: Invalid ID supplied + "404": + description: Pet not found + "405": + description: Validation exception + security: + - petstore_auth: + - write:pets + - read:pets + summary: Update an existing pet + tags: + - pet + /pet/findByStatus: + get: + description: Multiple status values can be provided with comma separated strings + operationId: findPetsByStatus + parameters: + - deprecated: true + description: Status values that need to be considered for filter + explode: false + in: query + name: status + required: true + schema: + items: + default: available + enum: + - available + - pending + - sold + type: string + type: array + style: form + responses: + "200": + content: + application/xml: + schema: + items: + $ref: '#/components/schemas/Pet' + type: array + application/json: + schema: + items: + $ref: '#/components/schemas/Pet' + type: array + description: successful operation + "400": + description: Invalid status value + security: + - petstore_auth: + - read:pets + summary: Finds Pets by status + tags: + - pet + /pet/findByTags: + get: + deprecated: true + description: "Multiple tags can be provided with comma separated strings. Use\ + \ tag1, tag2, tag3 for testing." + operationId: findPetsByTags + parameters: + - description: Tags to filter by + explode: false + in: query + name: tags + required: true + schema: + items: + type: string + type: array + style: form + responses: + "200": + content: + application/xml: + schema: + items: + $ref: '#/components/schemas/Pet' + type: array + application/json: + schema: + items: + $ref: '#/components/schemas/Pet' + type: array + description: successful operation + "400": + description: Invalid tag value + security: + - petstore_auth: + - read:pets + summary: Finds Pets by tags + tags: + - pet + /pet/{petId}: + delete: + description: "" + operationId: deletePet + parameters: + - explode: false + in: header + name: api_key + required: false + schema: + type: string + style: simple + - description: Pet id to delete + explode: false + in: path + name: petId + required: true + schema: + format: int64 + type: integer + style: simple + responses: + "400": + description: Invalid pet value + security: + - petstore_auth: + - write:pets + - read:pets + summary: Deletes a pet + tags: + - pet + get: + description: Returns a single pet + operationId: getPetById + parameters: + - description: ID of pet to return + explode: false + in: path + name: petId + required: true + schema: + format: int64 + type: integer + style: simple + responses: + "200": + content: + application/xml: + schema: + $ref: '#/components/schemas/Pet' + application/json: + schema: + $ref: '#/components/schemas/Pet' + description: successful operation + "400": + description: Invalid ID supplied + "404": + description: Pet not found + security: + - api_key: [] + summary: Find pet by ID + tags: + - pet + post: + description: "" + operationId: updatePetWithForm + parameters: + - description: ID of pet that needs to be updated + explode: false + in: path + name: petId + required: true + schema: + format: int64 + type: integer + style: simple + requestBody: + content: + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/updatePetWithForm_request' + responses: + "405": + description: Invalid input + security: + - petstore_auth: + - write:pets + - read:pets + summary: Updates a pet in the store with form data + tags: + - pet + /pet/{petId}/uploadImage: + post: + description: "" + operationId: uploadFile + parameters: + - description: ID of pet to update + explode: false + in: path + name: petId + required: true + schema: + format: int64 + type: integer + style: simple + requestBody: + content: + multipart/form-data: + schema: + $ref: '#/components/schemas/uploadFile_request' + responses: + "200": + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponse' + description: successful operation + security: + - petstore_auth: + - write:pets + - read:pets + summary: uploads an image + tags: + - pet + /store/inventory: + get: + description: Returns a map of status codes to quantities + operationId: getInventory + responses: + "200": + content: + application/json: + schema: + additionalProperties: + format: int32 + type: integer + type: object + description: successful operation + security: + - api_key: [] + summary: Returns pet inventories by status + tags: + - store + /store/order: + post: + description: "" + operationId: placeOrder + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Order' + description: order placed for purchasing the pet + required: true + responses: + "200": + content: + application/xml: + schema: + $ref: '#/components/schemas/Order' + application/json: + schema: + $ref: '#/components/schemas/Order' + description: successful operation + "400": + description: Invalid Order + summary: Place an order for a pet + tags: + - store + /store/order/{orderId}: + delete: + description: For valid response try integer IDs with value < 1000. Anything + above 1000 or nonintegers will generate API errors + operationId: deleteOrder + parameters: + - description: ID of the order that needs to be deleted + explode: false + in: path + name: orderId + required: true + schema: + type: string + style: simple + responses: + "400": + description: Invalid ID supplied + "404": + description: Order not found + summary: Delete purchase order by ID + tags: + - store + get: + description: For valid response try integer IDs with value <= 5 or > 10. Other + values will generate exceptions + operationId: getOrderById + parameters: + - description: ID of pet that needs to be fetched + explode: false + in: path + name: orderId + required: true + schema: + format: int64 + maximum: 5 + minimum: 1 + type: integer + style: simple + responses: + "200": + content: + application/xml: + schema: + $ref: '#/components/schemas/Order' + application/json: + schema: + $ref: '#/components/schemas/Order' + description: successful operation + "400": + description: Invalid ID supplied + "404": + description: Order not found + summary: Find purchase order by ID + tags: + - store + /user: + post: + description: This can only be done by the logged in user. + operationId: createUser + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/User' + description: Created user object + required: true + responses: + default: + description: successful operation + security: + - api_key: [] + summary: Create user + tags: + - user + /user/createWithArray: + post: + description: "" + operationId: createUsersWithArrayInput + requestBody: + $ref: '#/components/requestBodies/UserArray' + responses: + default: + description: successful operation + security: + - api_key: [] + summary: Creates list of users with given input array + tags: + - user + /user/createWithList: + post: + description: "" + operationId: createUsersWithListInput + requestBody: + $ref: '#/components/requestBodies/UserArray' + responses: + default: + description: successful operation + security: + - api_key: [] + summary: Creates list of users with given input array + tags: + - user + /user/login: + get: + description: "" + operationId: loginUser + parameters: + - description: The user name for login + explode: true + in: query + name: username + required: true + schema: + pattern: "^[a-zA-Z0-9]+[a-zA-Z0-9\\.\\-_]*[a-zA-Z0-9]+$" + type: string + style: form + - description: The password for login in clear text + explode: true + in: query + name: password + required: true + schema: + type: string + style: form + - description: The password for login in clear text + explode: true + in: query + name: int32_test + required: false + schema: + format: int32 + type: integer + style: form + - description: The password for login in clear text + explode: true + in: query + name: int64_test + required: false + schema: + format: int64 + type: integer + style: form + - description: The password for login in clear text + explode: true + in: query + name: float32_test + required: false + schema: + type: number + style: form + - description: The password for login in clear text + explode: true + in: query + name: float64_test + required: false + schema: + format: double + type: number + style: form + - description: The password for login in clear text + explode: true + in: query + name: boolean_test + required: false + schema: + type: boolean + style: form + responses: + "200": + content: + application/xml: + schema: + type: string + application/json: + schema: + type: string + description: successful operation + headers: + Set-Cookie: + description: Cookie authentication key for use with the `api_key` apiKey + authentication. + explode: false + schema: + example: AUTH_KEY=abcde12345; Path=/; HttpOnly + type: string + style: simple + X-Rate-Limit: + description: calls per hour allowed by the user + explode: false + schema: + format: int32 + type: integer + style: simple + X-Expires-After: + description: date in UTC when token expires + explode: false + schema: + format: date-time + type: string + style: simple + "400": + description: Invalid username/password supplied + summary: Logs user into the system + tags: + - user + /user/logout: + get: + description: "" + operationId: logoutUser + responses: + default: + description: successful operation + security: + - api_key: [] + summary: Logs out current logged in user session + tags: + - user + /user/{username}: + delete: + description: This can only be done by the logged in user. + operationId: deleteUser + parameters: + - description: The name that needs to be deleted + explode: false + in: path + name: username + required: true + schema: + type: string + style: simple + - description: boolean query parameter + explode: true + in: query + name: boolean_test + required: false + schema: + type: boolean + style: form + responses: + "400": + description: Invalid username supplied + "404": + description: User not found + security: + - api_key: [] + summary: Delete user + tags: + - user + get: + description: "" + operationId: getUserByName + parameters: + - description: The name that needs to be fetched. Use user1 for testing. + explode: false + in: path + name: username + required: true + schema: + type: string + style: simple + responses: + "200": + content: + application/xml: + schema: + $ref: '#/components/schemas/User' + application/json: + schema: + $ref: '#/components/schemas/User' + description: successful operation + "400": + description: Invalid username supplied + "404": + description: User not found + summary: Get user by user name + tags: + - user + put: + description: This can only be done by the logged in user. + operationId: updateUser + parameters: + - description: name that need to be deleted + explode: false + in: path + name: username + required: true + schema: + type: string + style: simple + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/User' + description: Updated user object + required: true + responses: + "400": + description: Invalid user supplied + "404": + description: User not found + security: + - api_key: [] + summary: Updated user + tags: + - user +components: + requestBodies: + UserArray: + content: + application/json: + schema: + items: + $ref: '#/components/schemas/User' + type: array + description: List of user object + required: true + Pet: + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + application/xml: + schema: + $ref: '#/components/schemas/Pet' + description: Pet object that needs to be added to the store + required: true + schemas: + OrderInfo: + description: An order info for a pets from the pet store + properties: + petId: + format: int64 + type: integer + quantity: + format: int32 + type: integer + shipDate: + format: date-time + type: string + title: Pet Order Info + type: object + xml: + name: OrderInfo + SpecialInfo: + description: An order info for a pets from the pet store + discriminator: + propertyName: type + properties: + promotion: + type: boolean + requireTest: + type: string + type: + type: string + required: + - requireTest + title: Pet Order Info + type: object + xml: + name: OrderInfo + Order: + allOf: + - $ref: '#/components/schemas/OrderInfo' + - $ref: '#/components/schemas/SpecialInfo' + description: An order for a pets from the pet store + example: + petId: 6 + quantity: 1 + comment: comment + id: 0 + shipDate: 2000-01-23T04:56:07.000+00:00 + complete: false + status: placed + properties: + id: + format: int64 + type: integer + petId: + format: int64 + type: integer + quantity: + format: int32 + type: integer + shipDate: + format: date-time + type: string + status: + description: Order Status + enum: + - placed + - approved + - delivered + type: string + complete: + default: false + type: boolean + comment: + nullable: true + type: string + required: + - comment + title: Pet Order + type: object + xml: + name: Order + Category: + description: A category for a pet + example: + name: name + id: 6 + nullable: true + properties: + id: + format: int64 + type: integer + name: + pattern: "^[a-zA-Z0-9]+[a-zA-Z0-9\\.\\-_]*[a-zA-Z0-9]+$" + type: string + title: Pet category + type: object + xml: + name: Category + User: + description: A User who is purchasing from the pet store + example: + firstName: firstName + lastName: lastName + password: password + userStatus: 6 + phone: phone + deepSliceModel: + - - - name: name + id: 1 + - name: name + id: 1 + - - name: name + id: 1 + - name: name + id: 1 + - - - name: name + id: 1 + - name: name + id: 1 + - - name: name + id: 1 + - name: name + id: 1 + id: 0 + deepSliceMap: + - - tag: + name: name + id: 1 + Pet: + - photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + - photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + - tag: + name: name + id: 1 + Pet: + - photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + - photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + - - tag: + name: name + id: 1 + Pet: + - photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + - photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + - tag: + name: name + id: 1 + Pet: + - photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + - photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + email: email + username: username + properties: + id: + format: int64 + type: integer + username: + type: string + firstName: + type: string + lastName: + type: string + email: + type: string + password: + type: string + phone: + nullable: true + type: string + userStatus: + description: User Status + format: int32 + type: integer + deepSliceModel: + description: An array 1-deep. + items: + description: An array 2-deep. + items: + description: An array 3-deep. + items: + $ref: '#/components/schemas/Tag' + type: array + type: array + nullable: true + type: array + deepSliceMap: + description: An array 1-deep. + items: + description: An array 2-deep. + items: + $ref: '#/components/schemas/an_Object' + type: array + type: array + required: + - deepSliceModel + title: a User + type: object + xml: + name: User + Tag: + description: A tag for a pet + example: + name: name + id: 1 + properties: + id: + format: int64 + type: integer + name: + type: string + title: Pet Tag + type: object + xml: + name: Tag + Pet: + description: A pet for sale in the pet store + example: + photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + properties: + id: + format: int64 + type: integer + category: + $ref: '#/components/schemas/Category' + name: + example: doggie + type: string + photoUrls: + items: + type: string + nullable: true + type: array + xml: + name: photoUrl + wrapped: true + tags: + items: + $ref: '#/components/schemas/Tag' + nullable: true + type: array + xml: + name: tag + wrapped: true + status: + deprecated: true + description: pet status in the store + enum: + - available + - pending + - sold + type: string + required: + - name + - photoUrls + title: a Pet + type: object + xml: + name: Pet + ApiResponse: + description: Describes the result of uploading an image resource + example: + code: 0 + type: type + message: message + properties: + code: + format: int32 + type: integer + type: + type: string + message: + type: string + title: An uploaded response + type: object + updatePetWithForm_request: + properties: + name: + description: Updated name of the pet + type: string + status: + description: Updated status of the pet + type: string + type: object + uploadFile_request: + properties: + additionalMetadata: + description: Additional data to pass to server + type: string + file: + description: file to upload + format: binary + type: string + type: object + an_Object: + description: An array 3-deep. + example: + tag: + name: name + id: 1 + Pet: + - photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + - photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + properties: + tag: + $ref: '#/components/schemas/Tag' + Pet: + description: An array of pet. + items: + $ref: '#/components/schemas/Pet' + type: array + title: an Object + type: object + securitySchemes: + petstore_auth: + flows: + implicit: + authorizationUrl: http://petstore.swagger.io/api/oauth/dialog + scopes: + write:pets: modify pets in your account + read:pets: read your pets + type: oauth2 + api_key: + in: header + name: api_key + type: apiKey diff --git a/samples/openapi3/server/petstore/go/go-petstore/go.mod b/samples/openapi3/server/petstore/go/go-petstore/go.mod new file mode 100644 index 00000000000..5886c8aa7e7 --- /dev/null +++ b/samples/openapi3/server/petstore/go/go-petstore/go.mod @@ -0,0 +1,5 @@ +module github.com/GIT_USER_ID/GIT_REPO_ID + +go 1.18 + +require github.com/go-chi/chi/v5 v5.0.8 diff --git a/samples/openapi3/server/petstore/go/go-petstore/go/api.go b/samples/openapi3/server/petstore/go/go-petstore/go/api.go new file mode 100644 index 00000000000..1f55c4e317d --- /dev/null +++ b/samples/openapi3/server/petstore/go/go-petstore/go/api.go @@ -0,0 +1,100 @@ +/* + * OpenAPI Petstore + * + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package petstoreserver + +import ( + "context" + "net/http" + "os" +) + + + +// PetAPIRouter defines the required methods for binding the api requests to a responses for the PetAPI +// The PetAPIRouter implementation should parse necessary information from the http request, +// pass the data to a PetAPIServicer to perform the required actions, then write the service results to the http response. +type PetAPIRouter interface { + AddPet(http.ResponseWriter, *http.Request) + DeletePet(http.ResponseWriter, *http.Request) + FindPetsByStatus(http.ResponseWriter, *http.Request) + // Deprecated + FindPetsByTags(http.ResponseWriter, *http.Request) + GetPetById(http.ResponseWriter, *http.Request) + UpdatePet(http.ResponseWriter, *http.Request) + UpdatePetWithForm(http.ResponseWriter, *http.Request) + UploadFile(http.ResponseWriter, *http.Request) +} +// StoreAPIRouter defines the required methods for binding the api requests to a responses for the StoreAPI +// The StoreAPIRouter implementation should parse necessary information from the http request, +// pass the data to a StoreAPIServicer to perform the required actions, then write the service results to the http response. +type StoreAPIRouter interface { + DeleteOrder(http.ResponseWriter, *http.Request) + GetInventory(http.ResponseWriter, *http.Request) + GetOrderById(http.ResponseWriter, *http.Request) + PlaceOrder(http.ResponseWriter, *http.Request) +} +// UserAPIRouter defines the required methods for binding the api requests to a responses for the UserAPI +// The UserAPIRouter implementation should parse necessary information from the http request, +// pass the data to a UserAPIServicer to perform the required actions, then write the service results to the http response. +type UserAPIRouter interface { + CreateUser(http.ResponseWriter, *http.Request) + CreateUsersWithArrayInput(http.ResponseWriter, *http.Request) + CreateUsersWithListInput(http.ResponseWriter, *http.Request) + DeleteUser(http.ResponseWriter, *http.Request) + GetUserByName(http.ResponseWriter, *http.Request) + LoginUser(http.ResponseWriter, *http.Request) + LogoutUser(http.ResponseWriter, *http.Request) + UpdateUser(http.ResponseWriter, *http.Request) +} + + +// PetAPIServicer defines the api actions for the PetAPI service +// This interface intended to stay up to date with the openapi yaml used to generate it, +// while the service implementation can be ignored with the .openapi-generator-ignore file +// and updated with the logic required for the API. +type PetAPIServicer interface { + AddPet(context.Context, Pet) (ImplResponse, error) + DeletePet(context.Context, int64, string) (ImplResponse, error) + FindPetsByStatus(context.Context, []string) (ImplResponse, error) + // Deprecated + FindPetsByTags(context.Context, []string) (ImplResponse, error) + GetPetById(context.Context, int64) (ImplResponse, error) + UpdatePet(context.Context, Pet) (ImplResponse, error) + UpdatePetWithForm(context.Context, int64, string, string) (ImplResponse, error) + UploadFile(context.Context, int64, string, *os.File) (ImplResponse, error) +} + + +// StoreAPIServicer defines the api actions for the StoreAPI service +// This interface intended to stay up to date with the openapi yaml used to generate it, +// while the service implementation can be ignored with the .openapi-generator-ignore file +// and updated with the logic required for the API. +type StoreAPIServicer interface { + DeleteOrder(context.Context, string) (ImplResponse, error) + GetInventory(context.Context) (ImplResponse, error) + GetOrderById(context.Context, int64) (ImplResponse, error) + PlaceOrder(context.Context, Order) (ImplResponse, error) +} + + +// UserAPIServicer defines the api actions for the UserAPI service +// This interface intended to stay up to date with the openapi yaml used to generate it, +// while the service implementation can be ignored with the .openapi-generator-ignore file +// and updated with the logic required for the API. +type UserAPIServicer interface { + CreateUser(context.Context, User) (ImplResponse, error) + CreateUsersWithArrayInput(context.Context, []User) (ImplResponse, error) + CreateUsersWithListInput(context.Context, []User) (ImplResponse, error) + DeleteUser(context.Context, string, bool) (ImplResponse, error) + GetUserByName(context.Context, string) (ImplResponse, error) + LoginUser(context.Context, string, string, int32, int64, float32, float64, bool) (ImplResponse, error) + LogoutUser(context.Context) (ImplResponse, error) + UpdateUser(context.Context, string, User) (ImplResponse, error) +} diff --git a/samples/openapi3/server/petstore/go/go-petstore/go/api_pet.go b/samples/openapi3/server/petstore/go/go-petstore/go/api_pet.go new file mode 100644 index 00000000000..0efd81a77e9 --- /dev/null +++ b/samples/openapi3/server/petstore/go/go-petstore/go/api_pet.go @@ -0,0 +1,283 @@ +/* + * OpenAPI Petstore + * + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package petstoreserver + +import ( + "encoding/json" + "net/http" + "strings" + + "github.com/go-chi/chi/v5" +) + +// PetAPIController binds http requests to an api service and writes the service results to the http response +type PetAPIController struct { + service PetAPIServicer + errorHandler ErrorHandler +} + +// PetAPIOption for how the controller is set up. +type PetAPIOption func(*PetAPIController) + +// WithPetAPIErrorHandler inject ErrorHandler into controller +func WithPetAPIErrorHandler(h ErrorHandler) PetAPIOption { + return func(c *PetAPIController) { + c.errorHandler = h + } +} + +// NewPetAPIController creates a default api controller +func NewPetAPIController(s PetAPIServicer, opts ...PetAPIOption) Router { + controller := &PetAPIController{ + service: s, + errorHandler: DefaultErrorHandler, + } + + for _, opt := range opts { + opt(controller) + } + + return controller +} + +// Routes returns all the api routes for the PetAPIController +func (c *PetAPIController) Routes() Routes { + return Routes{ + "AddPet": Route{ + strings.ToUpper("Post"), + "/v2/pet", + c.AddPet, + }, + "DeletePet": Route{ + strings.ToUpper("Delete"), + "/v2/pet/{petId}", + c.DeletePet, + }, + "FindPetsByStatus": Route{ + strings.ToUpper("Get"), + "/v2/pet/findByStatus", + c.FindPetsByStatus, + }, + "FindPetsByTags": Route{ + strings.ToUpper("Get"), + "/v2/pet/findByTags", + c.FindPetsByTags, + }, + "GetPetById": Route{ + strings.ToUpper("Get"), + "/v2/pet/{petId}", + c.GetPetById, + }, + "UpdatePet": Route{ + strings.ToUpper("Put"), + "/v2/pet", + c.UpdatePet, + }, + "UpdatePetWithForm": Route{ + strings.ToUpper("Post"), + "/v2/pet/{petId}", + c.UpdatePetWithForm, + }, + "UploadFile": Route{ + strings.ToUpper("Post"), + "/v2/pet/{petId}/uploadImage", + c.UploadFile, + }, + } +} + +// AddPet - Add a new pet to the store +func (c *PetAPIController) AddPet(w http.ResponseWriter, r *http.Request) { + petParam := Pet{} + d := json.NewDecoder(r.Body) + d.DisallowUnknownFields() + if err := d.Decode(&petParam); err != nil { + c.errorHandler(w, r, &ParsingError{Err: err}, nil) + return + } + if err := AssertPetRequired(petParam); err != nil { + c.errorHandler(w, r, err, nil) + return + } + if err := AssertPetConstraints(petParam); err != nil { + c.errorHandler(w, r, err, nil) + return + } + result, err := c.service.AddPet(r.Context(), petParam) + // If an error occurred, encode the error with the status code + if err != nil { + c.errorHandler(w, r, err, &result) + return + } + // If no error, encode the body and the result code + EncodeJSONResponse(result.Body, &result.Code, result.Headers, w) +} + +// DeletePet - Deletes a pet +func (c *PetAPIController) DeletePet(w http.ResponseWriter, r *http.Request) { + petIdParam, err := parseNumericParameter[int64]( + chi.URLParam(r, "petId"), + WithRequire[int64](parseInt64), + ) + if err != nil { + c.errorHandler(w, r, &ParsingError{Err: err}, nil) + return + } + apiKeyParam := r.Header.Get("api_key") + result, err := c.service.DeletePet(r.Context(), petIdParam, apiKeyParam) + // If an error occurred, encode the error with the status code + if err != nil { + c.errorHandler(w, r, err, &result) + return + } + // If no error, encode the body and the result code + EncodeJSONResponse(result.Body, &result.Code, result.Headers, w) +} + +// FindPetsByStatus - Finds Pets by status +func (c *PetAPIController) FindPetsByStatus(w http.ResponseWriter, r *http.Request) { + query := r.URL.Query() + statusParam := strings.Split(query.Get("status"), ",") + result, err := c.service.FindPetsByStatus(r.Context(), statusParam) + // If an error occurred, encode the error with the status code + if err != nil { + c.errorHandler(w, r, err, &result) + return + } + // If no error, encode the body and the result code + EncodeJSONResponse(result.Body, &result.Code, result.Headers, w) +} + +// FindPetsByTags - Finds Pets by tags +// Deprecated +func (c *PetAPIController) FindPetsByTags(w http.ResponseWriter, r *http.Request) { + query := r.URL.Query() + tagsParam := strings.Split(query.Get("tags"), ",") + result, err := c.service.FindPetsByTags(r.Context(), tagsParam) + // If an error occurred, encode the error with the status code + if err != nil { + c.errorHandler(w, r, err, &result) + return + } + // If no error, encode the body and the result code + EncodeJSONResponse(result.Body, &result.Code, result.Headers, w) +} + +// GetPetById - Find pet by ID +func (c *PetAPIController) GetPetById(w http.ResponseWriter, r *http.Request) { + petIdParam, err := parseNumericParameter[int64]( + chi.URLParam(r, "petId"), + WithRequire[int64](parseInt64), + ) + if err != nil { + c.errorHandler(w, r, &ParsingError{Err: err}, nil) + return + } + result, err := c.service.GetPetById(r.Context(), petIdParam) + // If an error occurred, encode the error with the status code + if err != nil { + c.errorHandler(w, r, err, &result) + return + } + // If no error, encode the body and the result code + EncodeJSONResponse(result.Body, &result.Code, result.Headers, w) +} + +// UpdatePet - Update an existing pet +func (c *PetAPIController) UpdatePet(w http.ResponseWriter, r *http.Request) { + petParam := Pet{} + d := json.NewDecoder(r.Body) + d.DisallowUnknownFields() + if err := d.Decode(&petParam); err != nil { + c.errorHandler(w, r, &ParsingError{Err: err}, nil) + return + } + if err := AssertPetRequired(petParam); err != nil { + c.errorHandler(w, r, err, nil) + return + } + if err := AssertPetConstraints(petParam); err != nil { + c.errorHandler(w, r, err, nil) + return + } + result, err := c.service.UpdatePet(r.Context(), petParam) + // If an error occurred, encode the error with the status code + if err != nil { + c.errorHandler(w, r, err, &result) + return + } + // If no error, encode the body and the result code + EncodeJSONResponse(result.Body, &result.Code, result.Headers, w) +} + +// UpdatePetWithForm - Updates a pet in the store with form data +func (c *PetAPIController) UpdatePetWithForm(w http.ResponseWriter, r *http.Request) { + if err := r.ParseForm(); err != nil { + c.errorHandler(w, r, &ParsingError{Err: err}, nil) + return + } + petIdParam, err := parseNumericParameter[int64]( + chi.URLParam(r, "petId"), + WithRequire[int64](parseInt64), + ) + if err != nil { + c.errorHandler(w, r, &ParsingError{Err: err}, nil) + return + } + + + nameParam := r.FormValue("name") + + + statusParam := r.FormValue("status") + result, err := c.service.UpdatePetWithForm(r.Context(), petIdParam, nameParam, statusParam) + // If an error occurred, encode the error with the status code + if err != nil { + c.errorHandler(w, r, err, &result) + return + } + // If no error, encode the body and the result code + EncodeJSONResponse(result.Body, &result.Code, result.Headers, w) +} + +// UploadFile - uploads an image +func (c *PetAPIController) UploadFile(w http.ResponseWriter, r *http.Request) { + if err := r.ParseMultipartForm(32 << 20); err != nil { + c.errorHandler(w, r, &ParsingError{Err: err}, nil) + return + } + petIdParam, err := parseNumericParameter[int64]( + chi.URLParam(r, "petId"), + WithRequire[int64](parseInt64), + ) + if err != nil { + c.errorHandler(w, r, &ParsingError{Err: err}, nil) + return + } + + + additionalMetadataParam := r.FormValue("additionalMetadata") + + fileParam, err := ReadFormFileToTempFile(r, "file") + if err != nil { + c.errorHandler(w, r, &ParsingError{Err: err}, nil) + return + } + + + result, err := c.service.UploadFile(r.Context(), petIdParam, additionalMetadataParam, fileParam) + // If an error occurred, encode the error with the status code + if err != nil { + c.errorHandler(w, r, err, &result) + return + } + // If no error, encode the body and the result code + EncodeJSONResponse(result.Body, &result.Code, result.Headers, w) +} diff --git a/samples/openapi3/server/petstore/go/go-petstore/go/api_pet_service.go b/samples/openapi3/server/petstore/go/go-petstore/go/api_pet_service.go new file mode 100644 index 00000000000..bda4cd89752 --- /dev/null +++ b/samples/openapi3/server/petstore/go/go-petstore/go/api_pet_service.go @@ -0,0 +1,141 @@ +/* + * OpenAPI Petstore + * + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package petstoreserver + +import ( + "context" + "net/http" + "errors" + "os" +) + +// PetAPIService is a service that implements the logic for the PetAPIServicer +// This service should implement the business logic for every endpoint for the PetAPI API. +// Include any external packages or services that will be required by this service. +type PetAPIService struct { +} + +// NewPetAPIService creates a default api service +func NewPetAPIService() PetAPIServicer { + return &PetAPIService{} +} + +// AddPet - Add a new pet to the store +func (s *PetAPIService) AddPet(ctx context.Context, pet Pet) (ImplResponse, error) { + // TODO - update AddPet with the required logic for this service method. + // Add api_pet_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation. + + // TODO: Uncomment the next line to return response Response(200, Pet{}) or use other options such as http.Ok ... + // return Response(200, Pet{}), nil + + // TODO: Uncomment the next line to return response Response(405, {}) or use other options such as http.Ok ... + // return Response(405, nil),nil + + return Response(http.StatusNotImplemented, nil), errors.New("AddPet method not implemented") +} + +// DeletePet - Deletes a pet +func (s *PetAPIService) DeletePet(ctx context.Context, petId int64, apiKey string) (ImplResponse, error) { + // TODO - update DeletePet with the required logic for this service method. + // Add api_pet_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation. + + // TODO: Uncomment the next line to return response Response(400, {}) or use other options such as http.Ok ... + // return Response(400, nil),nil + + return Response(http.StatusNotImplemented, nil), errors.New("DeletePet method not implemented") +} + +// FindPetsByStatus - Finds Pets by status +func (s *PetAPIService) FindPetsByStatus(ctx context.Context, status []string) (ImplResponse, error) { + // TODO - update FindPetsByStatus with the required logic for this service method. + // Add api_pet_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation. + + // TODO: Uncomment the next line to return response Response(200, []Pet{}) or use other options such as http.Ok ... + // return Response(200, []Pet{}), nil + + // TODO: Uncomment the next line to return response Response(400, {}) or use other options such as http.Ok ... + // return Response(400, nil),nil + + return Response(http.StatusNotImplemented, nil), errors.New("FindPetsByStatus method not implemented") +} + +// FindPetsByTags - Finds Pets by tags +// Deprecated +func (s *PetAPIService) FindPetsByTags(ctx context.Context, tags []string) (ImplResponse, error) { + // TODO - update FindPetsByTags with the required logic for this service method. + // Add api_pet_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation. + + // TODO: Uncomment the next line to return response Response(200, []Pet{}) or use other options such as http.Ok ... + // return Response(200, []Pet{}), nil + + // TODO: Uncomment the next line to return response Response(400, {}) or use other options such as http.Ok ... + // return Response(400, nil),nil + + return Response(http.StatusNotImplemented, nil), errors.New("FindPetsByTags method not implemented") +} + +// GetPetById - Find pet by ID +func (s *PetAPIService) GetPetById(ctx context.Context, petId int64) (ImplResponse, error) { + // TODO - update GetPetById with the required logic for this service method. + // Add api_pet_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation. + + // TODO: Uncomment the next line to return response Response(200, Pet{}) or use other options such as http.Ok ... + // return Response(200, Pet{}), nil + + // TODO: Uncomment the next line to return response Response(400, {}) or use other options such as http.Ok ... + // return Response(400, nil),nil + + // TODO: Uncomment the next line to return response Response(404, {}) or use other options such as http.Ok ... + // return Response(404, nil),nil + + return Response(http.StatusNotImplemented, nil), errors.New("GetPetById method not implemented") +} + +// UpdatePet - Update an existing pet +func (s *PetAPIService) UpdatePet(ctx context.Context, pet Pet) (ImplResponse, error) { + // TODO - update UpdatePet with the required logic for this service method. + // Add api_pet_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation. + + // TODO: Uncomment the next line to return response Response(200, Pet{}) or use other options such as http.Ok ... + // return Response(200, Pet{}), nil + + // TODO: Uncomment the next line to return response Response(400, {}) or use other options such as http.Ok ... + // return Response(400, nil),nil + + // TODO: Uncomment the next line to return response Response(404, {}) or use other options such as http.Ok ... + // return Response(404, nil),nil + + // TODO: Uncomment the next line to return response Response(405, {}) or use other options such as http.Ok ... + // return Response(405, nil),nil + + return Response(http.StatusNotImplemented, nil), errors.New("UpdatePet method not implemented") +} + +// UpdatePetWithForm - Updates a pet in the store with form data +func (s *PetAPIService) UpdatePetWithForm(ctx context.Context, petId int64, name string, status string) (ImplResponse, error) { + // TODO - update UpdatePetWithForm with the required logic for this service method. + // Add api_pet_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation. + + // TODO: Uncomment the next line to return response Response(405, {}) or use other options such as http.Ok ... + // return Response(405, nil),nil + + return Response(http.StatusNotImplemented, nil), errors.New("UpdatePetWithForm method not implemented") +} + +// UploadFile - uploads an image +func (s *PetAPIService) UploadFile(ctx context.Context, petId int64, additionalMetadata string, file *os.File) (ImplResponse, error) { + // TODO - update UploadFile with the required logic for this service method. + // Add api_pet_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation. + + // TODO: Uncomment the next line to return response Response(200, ApiResponse{}) or use other options such as http.Ok ... + // return Response(200, ApiResponse{}), nil + + return Response(http.StatusNotImplemented, nil), errors.New("UploadFile method not implemented") +} diff --git a/samples/openapi3/server/petstore/go/go-petstore/go/api_store.go b/samples/openapi3/server/petstore/go/go-petstore/go/api_store.go new file mode 100644 index 00000000000..7b131249078 --- /dev/null +++ b/samples/openapi3/server/petstore/go/go-petstore/go/api_store.go @@ -0,0 +1,148 @@ +/* + * OpenAPI Petstore + * + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package petstoreserver + +import ( + "encoding/json" + "net/http" + "strings" + + "github.com/go-chi/chi/v5" +) + +// StoreAPIController binds http requests to an api service and writes the service results to the http response +type StoreAPIController struct { + service StoreAPIServicer + errorHandler ErrorHandler +} + +// StoreAPIOption for how the controller is set up. +type StoreAPIOption func(*StoreAPIController) + +// WithStoreAPIErrorHandler inject ErrorHandler into controller +func WithStoreAPIErrorHandler(h ErrorHandler) StoreAPIOption { + return func(c *StoreAPIController) { + c.errorHandler = h + } +} + +// NewStoreAPIController creates a default api controller +func NewStoreAPIController(s StoreAPIServicer, opts ...StoreAPIOption) Router { + controller := &StoreAPIController{ + service: s, + errorHandler: DefaultErrorHandler, + } + + for _, opt := range opts { + opt(controller) + } + + return controller +} + +// Routes returns all the api routes for the StoreAPIController +func (c *StoreAPIController) Routes() Routes { + return Routes{ + "DeleteOrder": Route{ + strings.ToUpper("Delete"), + "/v2/store/order/{orderId}", + c.DeleteOrder, + }, + "GetInventory": Route{ + strings.ToUpper("Get"), + "/v2/store/inventory", + c.GetInventory, + }, + "GetOrderById": Route{ + strings.ToUpper("Get"), + "/v2/store/order/{orderId}", + c.GetOrderById, + }, + "PlaceOrder": Route{ + strings.ToUpper("Post"), + "/v2/store/order", + c.PlaceOrder, + }, + } +} + +// DeleteOrder - Delete purchase order by ID +func (c *StoreAPIController) DeleteOrder(w http.ResponseWriter, r *http.Request) { + orderIdParam := chi.URLParam(r, "orderId") + result, err := c.service.DeleteOrder(r.Context(), orderIdParam) + // If an error occurred, encode the error with the status code + if err != nil { + c.errorHandler(w, r, err, &result) + return + } + // If no error, encode the body and the result code + EncodeJSONResponse(result.Body, &result.Code, result.Headers, w) +} + +// GetInventory - Returns pet inventories by status +func (c *StoreAPIController) GetInventory(w http.ResponseWriter, r *http.Request) { + result, err := c.service.GetInventory(r.Context()) + // If an error occurred, encode the error with the status code + if err != nil { + c.errorHandler(w, r, err, &result) + return + } + // If no error, encode the body and the result code + EncodeJSONResponse(result.Body, &result.Code, result.Headers, w) +} + +// GetOrderById - Find purchase order by ID +func (c *StoreAPIController) GetOrderById(w http.ResponseWriter, r *http.Request) { + orderIdParam, err := parseNumericParameter[int64]( + chi.URLParam(r, "orderId"), + WithRequire[int64](parseInt64), + WithMinimum[int64](1), + WithMaximum[int64](5), + ) + if err != nil { + c.errorHandler(w, r, &ParsingError{Err: err}, nil) + return + } + result, err := c.service.GetOrderById(r.Context(), orderIdParam) + // If an error occurred, encode the error with the status code + if err != nil { + c.errorHandler(w, r, err, &result) + return + } + // If no error, encode the body and the result code + EncodeJSONResponse(result.Body, &result.Code, result.Headers, w) +} + +// PlaceOrder - Place an order for a pet +func (c *StoreAPIController) PlaceOrder(w http.ResponseWriter, r *http.Request) { + orderParam := Order{} + d := json.NewDecoder(r.Body) + d.DisallowUnknownFields() + if err := d.Decode(&orderParam); err != nil { + c.errorHandler(w, r, &ParsingError{Err: err}, nil) + return + } + if err := AssertOrderRequired(orderParam); err != nil { + c.errorHandler(w, r, err, nil) + return + } + if err := AssertOrderConstraints(orderParam); err != nil { + c.errorHandler(w, r, err, nil) + return + } + result, err := c.service.PlaceOrder(r.Context(), orderParam) + // If an error occurred, encode the error with the status code + if err != nil { + c.errorHandler(w, r, err, &result) + return + } + // If no error, encode the body and the result code + EncodeJSONResponse(result.Body, &result.Code, result.Headers, w) +} diff --git a/samples/openapi3/server/petstore/go/go-petstore/go/api_store_service.go b/samples/openapi3/server/petstore/go/go-petstore/go/api_store_service.go new file mode 100644 index 00000000000..3c24f24be81 --- /dev/null +++ b/samples/openapi3/server/petstore/go/go-petstore/go/api_store_service.go @@ -0,0 +1,83 @@ +/* + * OpenAPI Petstore + * + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package petstoreserver + +import ( + "context" + "net/http" + "errors" +) + +// StoreAPIService is a service that implements the logic for the StoreAPIServicer +// This service should implement the business logic for every endpoint for the StoreAPI API. +// Include any external packages or services that will be required by this service. +type StoreAPIService struct { +} + +// NewStoreAPIService creates a default api service +func NewStoreAPIService() StoreAPIServicer { + return &StoreAPIService{} +} + +// DeleteOrder - Delete purchase order by ID +func (s *StoreAPIService) DeleteOrder(ctx context.Context, orderId string) (ImplResponse, error) { + // TODO - update DeleteOrder with the required logic for this service method. + // Add api_store_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation. + + // TODO: Uncomment the next line to return response Response(400, {}) or use other options such as http.Ok ... + // return Response(400, nil),nil + + // TODO: Uncomment the next line to return response Response(404, {}) or use other options such as http.Ok ... + // return Response(404, nil),nil + + return Response(http.StatusNotImplemented, nil), errors.New("DeleteOrder method not implemented") +} + +// GetInventory - Returns pet inventories by status +func (s *StoreAPIService) GetInventory(ctx context.Context) (ImplResponse, error) { + // TODO - update GetInventory with the required logic for this service method. + // Add api_store_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation. + + // TODO: Uncomment the next line to return response Response(200, map[string]int32{}) or use other options such as http.Ok ... + // return Response(200, map[string]int32{}), nil + + return Response(http.StatusNotImplemented, nil), errors.New("GetInventory method not implemented") +} + +// GetOrderById - Find purchase order by ID +func (s *StoreAPIService) GetOrderById(ctx context.Context, orderId int64) (ImplResponse, error) { + // TODO - update GetOrderById with the required logic for this service method. + // Add api_store_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation. + + // TODO: Uncomment the next line to return response Response(200, Order{}) or use other options such as http.Ok ... + // return Response(200, Order{}), nil + + // TODO: Uncomment the next line to return response Response(400, {}) or use other options such as http.Ok ... + // return Response(400, nil),nil + + // TODO: Uncomment the next line to return response Response(404, {}) or use other options such as http.Ok ... + // return Response(404, nil),nil + + return Response(http.StatusNotImplemented, nil), errors.New("GetOrderById method not implemented") +} + +// PlaceOrder - Place an order for a pet +func (s *StoreAPIService) PlaceOrder(ctx context.Context, order Order) (ImplResponse, error) { + // TODO - update PlaceOrder with the required logic for this service method. + // Add api_store_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation. + + // TODO: Uncomment the next line to return response Response(200, Order{}) or use other options such as http.Ok ... + // return Response(200, Order{}), nil + + // TODO: Uncomment the next line to return response Response(400, {}) or use other options such as http.Ok ... + // return Response(400, nil),nil + + return Response(http.StatusNotImplemented, nil), errors.New("PlaceOrder method not implemented") +} diff --git a/samples/openapi3/server/petstore/go/go-petstore/go/api_user.go b/samples/openapi3/server/petstore/go/go-petstore/go/api_user.go new file mode 100644 index 00000000000..45b17d50303 --- /dev/null +++ b/samples/openapi3/server/petstore/go/go-petstore/go/api_user.go @@ -0,0 +1,301 @@ +/* + * OpenAPI Petstore + * + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package petstoreserver + +import ( + "encoding/json" + "net/http" + "strings" + + "github.com/go-chi/chi/v5" +) + +// UserAPIController binds http requests to an api service and writes the service results to the http response +type UserAPIController struct { + service UserAPIServicer + errorHandler ErrorHandler +} + +// UserAPIOption for how the controller is set up. +type UserAPIOption func(*UserAPIController) + +// WithUserAPIErrorHandler inject ErrorHandler into controller +func WithUserAPIErrorHandler(h ErrorHandler) UserAPIOption { + return func(c *UserAPIController) { + c.errorHandler = h + } +} + +// NewUserAPIController creates a default api controller +func NewUserAPIController(s UserAPIServicer, opts ...UserAPIOption) Router { + controller := &UserAPIController{ + service: s, + errorHandler: DefaultErrorHandler, + } + + for _, opt := range opts { + opt(controller) + } + + return controller +} + +// Routes returns all the api routes for the UserAPIController +func (c *UserAPIController) Routes() Routes { + return Routes{ + "CreateUser": Route{ + strings.ToUpper("Post"), + "/v2/user", + c.CreateUser, + }, + "CreateUsersWithArrayInput": Route{ + strings.ToUpper("Post"), + "/v2/user/createWithArray", + c.CreateUsersWithArrayInput, + }, + "CreateUsersWithListInput": Route{ + strings.ToUpper("Post"), + "/v2/user/createWithList", + c.CreateUsersWithListInput, + }, + "DeleteUser": Route{ + strings.ToUpper("Delete"), + "/v2/user/{username}", + c.DeleteUser, + }, + "GetUserByName": Route{ + strings.ToUpper("Get"), + "/v2/user/{username}", + c.GetUserByName, + }, + "LoginUser": Route{ + strings.ToUpper("Get"), + "/v2/user/login", + c.LoginUser, + }, + "LogoutUser": Route{ + strings.ToUpper("Get"), + "/v2/user/logout", + c.LogoutUser, + }, + "UpdateUser": Route{ + strings.ToUpper("Put"), + "/v2/user/{username}", + c.UpdateUser, + }, + } +} + +// CreateUser - Create user +func (c *UserAPIController) CreateUser(w http.ResponseWriter, r *http.Request) { + userParam := User{} + d := json.NewDecoder(r.Body) + d.DisallowUnknownFields() + if err := d.Decode(&userParam); err != nil { + c.errorHandler(w, r, &ParsingError{Err: err}, nil) + return + } + if err := AssertUserRequired(userParam); err != nil { + c.errorHandler(w, r, err, nil) + return + } + if err := AssertUserConstraints(userParam); err != nil { + c.errorHandler(w, r, err, nil) + return + } + result, err := c.service.CreateUser(r.Context(), userParam) + // If an error occurred, encode the error with the status code + if err != nil { + c.errorHandler(w, r, err, &result) + return + } + // If no error, encode the body and the result code + EncodeJSONResponse(result.Body, &result.Code, result.Headers, w) +} + +// CreateUsersWithArrayInput - Creates list of users with given input array +func (c *UserAPIController) CreateUsersWithArrayInput(w http.ResponseWriter, r *http.Request) { + userParam := []User{} + d := json.NewDecoder(r.Body) + d.DisallowUnknownFields() + if err := d.Decode(&userParam); err != nil { + c.errorHandler(w, r, &ParsingError{Err: err}, nil) + return + } + for _, el := range userParam { + if err := AssertUserRequired(el); err != nil { + c.errorHandler(w, r, err, nil) + return + } + } + result, err := c.service.CreateUsersWithArrayInput(r.Context(), userParam) + // If an error occurred, encode the error with the status code + if err != nil { + c.errorHandler(w, r, err, &result) + return + } + // If no error, encode the body and the result code + EncodeJSONResponse(result.Body, &result.Code, result.Headers, w) +} + +// CreateUsersWithListInput - Creates list of users with given input array +func (c *UserAPIController) CreateUsersWithListInput(w http.ResponseWriter, r *http.Request) { + userParam := []User{} + d := json.NewDecoder(r.Body) + d.DisallowUnknownFields() + if err := d.Decode(&userParam); err != nil { + c.errorHandler(w, r, &ParsingError{Err: err}, nil) + return + } + for _, el := range userParam { + if err := AssertUserRequired(el); err != nil { + c.errorHandler(w, r, err, nil) + return + } + } + result, err := c.service.CreateUsersWithListInput(r.Context(), userParam) + // If an error occurred, encode the error with the status code + if err != nil { + c.errorHandler(w, r, err, &result) + return + } + // If no error, encode the body and the result code + EncodeJSONResponse(result.Body, &result.Code, result.Headers, w) +} + +// DeleteUser - Delete user +func (c *UserAPIController) DeleteUser(w http.ResponseWriter, r *http.Request) { + query := r.URL.Query() + usernameParam := chi.URLParam(r, "username") + booleanTestParam, err := parseBoolParameter( + query.Get("boolean_test"), + WithParse[bool](parseBool), + ) + if err != nil { + w.WriteHeader(500) + return + } + result, err := c.service.DeleteUser(r.Context(), usernameParam, booleanTestParam) + // If an error occurred, encode the error with the status code + if err != nil { + c.errorHandler(w, r, err, &result) + return + } + // If no error, encode the body and the result code + EncodeJSONResponse(result.Body, &result.Code, result.Headers, w) +} + +// GetUserByName - Get user by user name +func (c *UserAPIController) GetUserByName(w http.ResponseWriter, r *http.Request) { + usernameParam := chi.URLParam(r, "username") + result, err := c.service.GetUserByName(r.Context(), usernameParam) + // If an error occurred, encode the error with the status code + if err != nil { + c.errorHandler(w, r, err, &result) + return + } + // If no error, encode the body and the result code + EncodeJSONResponse(result.Body, &result.Code, result.Headers, w) +} + +// LoginUser - Logs user into the system +func (c *UserAPIController) LoginUser(w http.ResponseWriter, r *http.Request) { + query := r.URL.Query() + usernameParam := query.Get("username") + passwordParam := query.Get("password") + int32TestParam, err := parseNumericParameter[int32]( + query.Get("int32_test"), + WithParse[int32](parseInt32), + ) + if err != nil { + c.errorHandler(w, r, &ParsingError{Err: err}, nil) + return + } + int64TestParam, err := parseNumericParameter[int64]( + query.Get("int64_test"), + WithParse[int64](parseInt64), + ) + if err != nil { + c.errorHandler(w, r, &ParsingError{Err: err}, nil) + return + } + float32TestParam, err := parseNumericParameter[float32]( + query.Get("float32_test"), + WithParse[float32](parseFloat32), + ) + if err != nil { + c.errorHandler(w, r, &ParsingError{Err: err}, nil) + return + } + float64TestParam, err := parseNumericParameter[float64]( + query.Get("float64_test"), + WithParse[float64](parseFloat64), + ) + if err != nil { + c.errorHandler(w, r, &ParsingError{Err: err}, nil) + return + } + booleanTestParam, err := parseBoolParameter( + query.Get("boolean_test"), + WithParse[bool](parseBool), + ) + if err != nil { + w.WriteHeader(500) + return + } + result, err := c.service.LoginUser(r.Context(), usernameParam, passwordParam, int32TestParam, int64TestParam, float32TestParam, float64TestParam, booleanTestParam) + // If an error occurred, encode the error with the status code + if err != nil { + c.errorHandler(w, r, err, &result) + return + } + // If no error, encode the body and the result code + EncodeJSONResponse(result.Body, &result.Code, result.Headers, w) +} + +// LogoutUser - Logs out current logged in user session +func (c *UserAPIController) LogoutUser(w http.ResponseWriter, r *http.Request) { + result, err := c.service.LogoutUser(r.Context()) + // If an error occurred, encode the error with the status code + if err != nil { + c.errorHandler(w, r, err, &result) + return + } + // If no error, encode the body and the result code + EncodeJSONResponse(result.Body, &result.Code, result.Headers, w) +} + +// UpdateUser - Updated user +func (c *UserAPIController) UpdateUser(w http.ResponseWriter, r *http.Request) { + usernameParam := chi.URLParam(r, "username") + userParam := User{} + d := json.NewDecoder(r.Body) + d.DisallowUnknownFields() + if err := d.Decode(&userParam); err != nil { + c.errorHandler(w, r, &ParsingError{Err: err}, nil) + return + } + if err := AssertUserRequired(userParam); err != nil { + c.errorHandler(w, r, err, nil) + return + } + if err := AssertUserConstraints(userParam); err != nil { + c.errorHandler(w, r, err, nil) + return + } + result, err := c.service.UpdateUser(r.Context(), usernameParam, userParam) + // If an error occurred, encode the error with the status code + if err != nil { + c.errorHandler(w, r, err, &result) + return + } + // If no error, encode the body and the result code + EncodeJSONResponse(result.Body, &result.Code, result.Headers, w) +} diff --git a/samples/openapi3/server/petstore/go/go-petstore/go/api_user_service.go b/samples/openapi3/server/petstore/go/go-petstore/go/api_user_service.go new file mode 100644 index 00000000000..22442c635b4 --- /dev/null +++ b/samples/openapi3/server/petstore/go/go-petstore/go/api_user_service.go @@ -0,0 +1,130 @@ +/* + * OpenAPI Petstore + * + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package petstoreserver + +import ( + "context" + "net/http" + "errors" +) + +// UserAPIService is a service that implements the logic for the UserAPIServicer +// This service should implement the business logic for every endpoint for the UserAPI API. +// Include any external packages or services that will be required by this service. +type UserAPIService struct { +} + +// NewUserAPIService creates a default api service +func NewUserAPIService() UserAPIServicer { + return &UserAPIService{} +} + +// CreateUser - Create user +func (s *UserAPIService) CreateUser(ctx context.Context, user User) (ImplResponse, error) { + // TODO - update CreateUser with the required logic for this service method. + // Add api_user_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation. + + // TODO: Uncomment the next line to return response Response(0, {}) or use other options such as http.Ok ... + // return Response(0, nil),nil + + return Response(http.StatusNotImplemented, nil), errors.New("CreateUser method not implemented") +} + +// CreateUsersWithArrayInput - Creates list of users with given input array +func (s *UserAPIService) CreateUsersWithArrayInput(ctx context.Context, user []User) (ImplResponse, error) { + // TODO - update CreateUsersWithArrayInput with the required logic for this service method. + // Add api_user_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation. + + // TODO: Uncomment the next line to return response Response(0, {}) or use other options such as http.Ok ... + // return Response(0, nil),nil + + return Response(http.StatusNotImplemented, nil), errors.New("CreateUsersWithArrayInput method not implemented") +} + +// CreateUsersWithListInput - Creates list of users with given input array +func (s *UserAPIService) CreateUsersWithListInput(ctx context.Context, user []User) (ImplResponse, error) { + // TODO - update CreateUsersWithListInput with the required logic for this service method. + // Add api_user_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation. + + // TODO: Uncomment the next line to return response Response(0, {}) or use other options such as http.Ok ... + // return Response(0, nil),nil + + return Response(http.StatusNotImplemented, nil), errors.New("CreateUsersWithListInput method not implemented") +} + +// DeleteUser - Delete user +func (s *UserAPIService) DeleteUser(ctx context.Context, username string, booleanTest bool) (ImplResponse, error) { + // TODO - update DeleteUser with the required logic for this service method. + // Add api_user_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation. + + // TODO: Uncomment the next line to return response Response(400, {}) or use other options such as http.Ok ... + // return Response(400, nil),nil + + // TODO: Uncomment the next line to return response Response(404, {}) or use other options such as http.Ok ... + // return Response(404, nil),nil + + return Response(http.StatusNotImplemented, nil), errors.New("DeleteUser method not implemented") +} + +// GetUserByName - Get user by user name +func (s *UserAPIService) GetUserByName(ctx context.Context, username string) (ImplResponse, error) { + // TODO - update GetUserByName with the required logic for this service method. + // Add api_user_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation. + + // TODO: Uncomment the next line to return response Response(200, User{}) or use other options such as http.Ok ... + // return Response(200, User{}), nil + + // TODO: Uncomment the next line to return response Response(400, {}) or use other options such as http.Ok ... + // return Response(400, nil),nil + + // TODO: Uncomment the next line to return response Response(404, {}) or use other options such as http.Ok ... + // return Response(404, nil),nil + + return Response(http.StatusNotImplemented, nil), errors.New("GetUserByName method not implemented") +} + +// LoginUser - Logs user into the system +func (s *UserAPIService) LoginUser(ctx context.Context, username string, password string, int32Test int32, int64Test int64, float32Test float32, float64Test float64, booleanTest bool) (ImplResponse, error) { + // TODO - update LoginUser with the required logic for this service method. + // Add api_user_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation. + + // TODO: Uncomment the next line to return response Response(200, string{}) or use other options such as http.Ok ... + // return Response(200, string{}), nil + + // TODO: Uncomment the next line to return response Response(400, {}) or use other options such as http.Ok ... + // return Response(400, nil),nil + + return Response(http.StatusNotImplemented, nil), errors.New("LoginUser method not implemented") +} + +// LogoutUser - Logs out current logged in user session +func (s *UserAPIService) LogoutUser(ctx context.Context) (ImplResponse, error) { + // TODO - update LogoutUser with the required logic for this service method. + // Add api_user_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation. + + // TODO: Uncomment the next line to return response Response(0, {}) or use other options such as http.Ok ... + // return Response(0, nil),nil + + return Response(http.StatusNotImplemented, nil), errors.New("LogoutUser method not implemented") +} + +// UpdateUser - Updated user +func (s *UserAPIService) UpdateUser(ctx context.Context, username string, user User) (ImplResponse, error) { + // TODO - update UpdateUser with the required logic for this service method. + // Add api_user_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation. + + // TODO: Uncomment the next line to return response Response(400, {}) or use other options such as http.Ok ... + // return Response(400, nil),nil + + // TODO: Uncomment the next line to return response Response(404, {}) or use other options such as http.Ok ... + // return Response(404, nil),nil + + return Response(http.StatusNotImplemented, nil), errors.New("UpdateUser method not implemented") +} diff --git a/samples/openapi3/server/petstore/go/go-petstore/go/error.go b/samples/openapi3/server/petstore/go/go-petstore/go/error.go new file mode 100644 index 00000000000..2c0b010fe8d --- /dev/null +++ b/samples/openapi3/server/petstore/go/go-petstore/go/error.go @@ -0,0 +1,62 @@ +/* + * OpenAPI Petstore + * + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package petstoreserver + +import ( + "errors" + "fmt" + "net/http" +) + +var ( + // ErrTypeAssertionError is thrown when type an interface does not match the asserted type + ErrTypeAssertionError = errors.New("unable to assert type") +) + +// ParsingError indicates that an error has occurred when parsing request parameters +type ParsingError struct { + Err error +} + +func (e *ParsingError) Unwrap() error { + return e.Err +} + +func (e *ParsingError) Error() string { + return e.Err.Error() +} + +// RequiredError indicates that an error has occurred when parsing request parameters +type RequiredError struct { + Field string +} + +func (e *RequiredError) Error() string { + return fmt.Sprintf("required field '%s' is zero value.", e.Field) +} + +// ErrorHandler defines the required method for handling error. You may implement it and inject this into a controller if +// you would like errors to be handled differently from the DefaultErrorHandler +type ErrorHandler func(w http.ResponseWriter, r *http.Request, err error, result *ImplResponse) + +// DefaultErrorHandler defines the default logic on how to handle errors from the controller. Any errors from parsing +// request params will return a StatusBadRequest. Otherwise, the error code originating from the servicer will be used. +func DefaultErrorHandler(w http.ResponseWriter, r *http.Request, err error, result *ImplResponse) { + if _, ok := err.(*ParsingError); ok { + // Handle parsing errors + EncodeJSONResponse(err.Error(), func(i int) *int { return &i }(http.StatusBadRequest), map[string][]string{}, w) + } else if _, ok := err.(*RequiredError); ok { + // Handle missing required errors + EncodeJSONResponse(err.Error(), func(i int) *int { return &i }(http.StatusUnprocessableEntity), map[string][]string{}, w) + } else { + // Handle all other errors + EncodeJSONResponse(err.Error(), &result.Code, result.Headers, w) + } +} diff --git a/samples/openapi3/server/petstore/go/go-petstore/go/helpers.go b/samples/openapi3/server/petstore/go/go-petstore/go/helpers.go new file mode 100644 index 00000000000..078da22b8fa --- /dev/null +++ b/samples/openapi3/server/petstore/go/go-petstore/go/helpers.go @@ -0,0 +1,70 @@ +/* + * OpenAPI Petstore + * + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package petstoreserver + +import ( + "reflect" +) + +// Response return a ImplResponse struct filled +func Response(code int, body interface{}) ImplResponse { + return ImplResponse { + Code: code, + Headers: nil, + Body: body, + } +} + +// ResponseWithHeaders return a ImplResponse struct filled, including headers +func ResponseWithHeaders(code int, headers map[string][]string, body interface{}) ImplResponse { + return ImplResponse { + Code: code, + Headers: headers, + Body: body, + } +} + +// IsZeroValue checks if the val is the zero-ed value. +func IsZeroValue(val interface{}) bool { + return val == nil || reflect.DeepEqual(val, reflect.Zero(reflect.TypeOf(val)).Interface()) +} + +// AssertRecurseInterfaceRequired recursively checks each struct in a slice against the callback. +// This method traverse nested slices in a preorder fashion. +func AssertRecurseInterfaceRequired[T any](obj interface{}, callback func(T) error) error { + return AssertRecurseValueRequired(reflect.ValueOf(obj), callback) +} + +// AssertRecurseValueRequired checks each struct in the nested slice against the callback. +// This method traverse nested slices in a preorder fashion. ErrTypeAssertionError is thrown if +// the underlying struct does not match type T. +func AssertRecurseValueRequired[T any](value reflect.Value, callback func(T) error) error { + switch value.Kind() { + // If it is a struct we check using callback + case reflect.Struct: + obj, ok := value.Interface().(T) + if !ok { + return ErrTypeAssertionError + } + + if err := callback(obj); err != nil { + return err + } + + // If it is a slice we continue recursion + case reflect.Slice: + for i := 0; i < value.Len(); i += 1 { + if err := AssertRecurseValueRequired(value.Index(i), callback); err != nil { + return err + } + } + } + return nil +} diff --git a/samples/openapi3/server/petstore/go/go-petstore/go/impl.go b/samples/openapi3/server/petstore/go/go-petstore/go/impl.go new file mode 100644 index 00000000000..7bfb815be5e --- /dev/null +++ b/samples/openapi3/server/petstore/go/go-petstore/go/impl.go @@ -0,0 +1,17 @@ +/* + * OpenAPI Petstore + * + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package petstoreserver + +// ImplResponse defines an implementation response with error code and the associated body +type ImplResponse struct { + Code int + Headers map[string][]string + Body interface{} +} diff --git a/samples/openapi3/server/petstore/go/go-petstore/go/logger.go b/samples/openapi3/server/petstore/go/go-petstore/go/logger.go new file mode 100644 index 00000000000..08cc0ea3f1d --- /dev/null +++ b/samples/openapi3/server/petstore/go/go-petstore/go/logger.go @@ -0,0 +1,32 @@ +/* + * OpenAPI Petstore + * + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package petstoreserver + +import ( + "log" + "net/http" + "time" +) + +func Logger(inner http.Handler, name string) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + start := time.Now() + + inner.ServeHTTP(w, r) + + log.Printf( + "%s %s %s %s", + r.Method, + r.RequestURI, + name, + time.Since(start), + ) + }) +} diff --git a/samples/openapi3/server/petstore/go/go-petstore/go/model_an_object.go b/samples/openapi3/server/petstore/go/go-petstore/go/model_an_object.go new file mode 100644 index 00000000000..ece30644b87 --- /dev/null +++ b/samples/openapi3/server/petstore/go/go-petstore/go/model_an_object.go @@ -0,0 +1,40 @@ +/* + * OpenAPI Petstore + * + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package petstoreserver + + + + +// AnObject - An array 3-deep. +type AnObject struct { + + Tag Tag `json:"tag,omitempty"` + + // An array of pet. + Pet []Pet `json:"Pet,omitempty"` +} + +// AssertAnObjectRequired checks if the required fields are not zero-ed +func AssertAnObjectRequired(obj AnObject) error { + if err := AssertTagRequired(obj.Tag); err != nil { + return err + } + for _, el := range obj.Pet { + if err := AssertPetRequired(el); err != nil { + return err + } + } + return nil +} + +// AssertAnObjectConstraints checks if the values respects the defined constraints +func AssertAnObjectConstraints(obj AnObject) error { + return nil +} diff --git a/samples/openapi3/server/petstore/go/go-petstore/go/model_api_response.go b/samples/openapi3/server/petstore/go/go-petstore/go/model_api_response.go new file mode 100644 index 00000000000..795fed14f6e --- /dev/null +++ b/samples/openapi3/server/petstore/go/go-petstore/go/model_api_response.go @@ -0,0 +1,33 @@ +/* + * OpenAPI Petstore + * + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package petstoreserver + + + + +// ApiResponse - Describes the result of uploading an image resource +type ApiResponse struct { + + Code int32 `json:"code,omitempty"` + + Type string `json:"type,omitempty"` + + Message string `json:"message,omitempty"` +} + +// AssertApiResponseRequired checks if the required fields are not zero-ed +func AssertApiResponseRequired(obj ApiResponse) error { + return nil +} + +// AssertApiResponseConstraints checks if the values respects the defined constraints +func AssertApiResponseConstraints(obj ApiResponse) error { + return nil +} diff --git a/samples/openapi3/server/petstore/go/go-petstore/go/model_category.go b/samples/openapi3/server/petstore/go/go-petstore/go/model_category.go new file mode 100644 index 00000000000..e7c13aeaa9f --- /dev/null +++ b/samples/openapi3/server/petstore/go/go-petstore/go/model_category.go @@ -0,0 +1,31 @@ +/* + * OpenAPI Petstore + * + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package petstoreserver + + + + +// Category - A category for a pet +type Category struct { + + Id int64 `json:"id,omitempty"` + + Name string `json:"name,omitempty"` +} + +// AssertCategoryRequired checks if the required fields are not zero-ed +func AssertCategoryRequired(obj Category) error { + return nil +} + +// AssertCategoryConstraints checks if the values respects the defined constraints +func AssertCategoryConstraints(obj Category) error { + return nil +} diff --git a/samples/openapi3/server/petstore/go/go-petstore/go/model_order.go b/samples/openapi3/server/petstore/go/go-petstore/go/model_order.go new file mode 100644 index 00000000000..069897e6b3d --- /dev/null +++ b/samples/openapi3/server/petstore/go/go-petstore/go/model_order.go @@ -0,0 +1,61 @@ +/* + * OpenAPI Petstore + * + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package petstoreserver + + +import ( + "time" +) + + + +// Order - An order for a pets from the pet store +type Order struct { + SpecialInfo + + Id int64 `json:"id,omitempty"` + + PetId int64 `json:"petId,omitempty"` + + Quantity int32 `json:"quantity,omitempty"` + + ShipDate time.Time `json:"shipDate,omitempty"` + + // Order Status + Status string `json:"status,omitempty"` + + Complete bool `json:"complete,omitempty"` + + Comment *string `json:"comment"` +} + +// AssertOrderRequired checks if the required fields are not zero-ed +func AssertOrderRequired(obj Order) error { + elements := map[string]interface{}{ + "comment": obj.Comment, + "requireTest": obj.RequireTest, + } + for name, el := range elements { + if isZero := IsZeroValue(el); isZero { + return &RequiredError{Field: name} + } + } + + if err := AssertSpecialInfoRequired(obj.SpecialInfo); err != nil { + return err + } + + return nil +} + +// AssertOrderConstraints checks if the values respects the defined constraints +func AssertOrderConstraints(obj Order) error { + return nil +} diff --git a/samples/openapi3/server/petstore/go/go-petstore/go/model_order_info.go b/samples/openapi3/server/petstore/go/go-petstore/go/model_order_info.go new file mode 100644 index 00000000000..4426570b024 --- /dev/null +++ b/samples/openapi3/server/petstore/go/go-petstore/go/model_order_info.go @@ -0,0 +1,37 @@ +/* + * OpenAPI Petstore + * + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package petstoreserver + + +import ( + "time" +) + + + +// OrderInfo - An order info for a pets from the pet store +type OrderInfo struct { + + PetId int64 `json:"petId,omitempty"` + + Quantity int32 `json:"quantity,omitempty"` + + ShipDate time.Time `json:"shipDate,omitempty"` +} + +// AssertOrderInfoRequired checks if the required fields are not zero-ed +func AssertOrderInfoRequired(obj OrderInfo) error { + return nil +} + +// AssertOrderInfoConstraints checks if the values respects the defined constraints +func AssertOrderInfoConstraints(obj OrderInfo) error { + return nil +} diff --git a/samples/openapi3/server/petstore/go/go-petstore/go/model_pet.go b/samples/openapi3/server/petstore/go/go-petstore/go/model_pet.go new file mode 100644 index 00000000000..6226912d13f --- /dev/null +++ b/samples/openapi3/server/petstore/go/go-petstore/go/model_pet.go @@ -0,0 +1,63 @@ +/* + * OpenAPI Petstore + * + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package petstoreserver + + + + +// Pet - A pet for sale in the pet store +type Pet struct { + + Id int64 `json:"id,omitempty"` + + Category *Category `json:"category,omitempty"` + + Name string `json:"name"` + + PhotoUrls *[]string `json:"photoUrls"` + + Tags *[]Tag `json:"tags,omitempty"` + + // pet status in the store + // Deprecated + Status string `json:"status,omitempty"` +} + +// AssertPetRequired checks if the required fields are not zero-ed +func AssertPetRequired(obj Pet) error { + elements := map[string]interface{}{ + "name": obj.Name, + "photoUrls": obj.PhotoUrls, + } + for name, el := range elements { + if isZero := IsZeroValue(el); isZero { + return &RequiredError{Field: name} + } + } + + if obj.Category != nil { + if err := AssertCategoryRequired(*obj.Category); err != nil { + return err + } + } + if obj.Tags != nil { + for _, el := range *obj.Tags { + if err := AssertTagRequired(el); err != nil { + return err + } + } + } + return nil +} + +// AssertPetConstraints checks if the values respects the defined constraints +func AssertPetConstraints(obj Pet) error { + return nil +} diff --git a/samples/openapi3/server/petstore/go/go-petstore/go/model_special_info.go b/samples/openapi3/server/petstore/go/go-petstore/go/model_special_info.go new file mode 100644 index 00000000000..267217d4385 --- /dev/null +++ b/samples/openapi3/server/petstore/go/go-petstore/go/model_special_info.go @@ -0,0 +1,42 @@ +/* + * OpenAPI Petstore + * + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package petstoreserver + + + + +// SpecialInfo - An order info for a pets from the pet store +type SpecialInfo struct { + + Promotion bool `json:"promotion,omitempty"` + + RequireTest string `json:"requireTest"` + + Type string `json:"type,omitempty"` +} + +// AssertSpecialInfoRequired checks if the required fields are not zero-ed +func AssertSpecialInfoRequired(obj SpecialInfo) error { + elements := map[string]interface{}{ + "requireTest": obj.RequireTest, + } + for name, el := range elements { + if isZero := IsZeroValue(el); isZero { + return &RequiredError{Field: name} + } + } + + return nil +} + +// AssertSpecialInfoConstraints checks if the values respects the defined constraints +func AssertSpecialInfoConstraints(obj SpecialInfo) error { + return nil +} diff --git a/samples/openapi3/server/petstore/go/go-petstore/go/model_tag.go b/samples/openapi3/server/petstore/go/go-petstore/go/model_tag.go new file mode 100644 index 00000000000..8b1a4facbae --- /dev/null +++ b/samples/openapi3/server/petstore/go/go-petstore/go/model_tag.go @@ -0,0 +1,31 @@ +/* + * OpenAPI Petstore + * + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package petstoreserver + + + + +// Tag - A tag for a pet +type Tag struct { + + Id int64 `json:"id,omitempty"` + + Name string `json:"name,omitempty"` +} + +// AssertTagRequired checks if the required fields are not zero-ed +func AssertTagRequired(obj Tag) error { + return nil +} + +// AssertTagConstraints checks if the values respects the defined constraints +func AssertTagConstraints(obj Tag) error { + return nil +} diff --git a/samples/openapi3/server/petstore/go/go-petstore/go/model_user.go b/samples/openapi3/server/petstore/go/go-petstore/go/model_user.go new file mode 100644 index 00000000000..1e0a432e8d4 --- /dev/null +++ b/samples/openapi3/server/petstore/go/go-petstore/go/model_user.go @@ -0,0 +1,67 @@ +/* + * OpenAPI Petstore + * + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package petstoreserver + + + + +// User - A User who is purchasing from the pet store +type User struct { + + Id int64 `json:"id,omitempty"` + + Username string `json:"username,omitempty"` + + FirstName string `json:"firstName,omitempty"` + + LastName string `json:"lastName,omitempty"` + + Email string `json:"email,omitempty"` + + Password string `json:"password,omitempty"` + + Phone *string `json:"phone,omitempty"` + + // User Status + UserStatus int32 `json:"userStatus,omitempty"` + + // An array 1-deep. + DeepSliceModel *[][][]Tag `json:"deepSliceModel"` + + // An array 1-deep. + DeepSliceMap [][]AnObject `json:"deepSliceMap,omitempty"` +} + +// AssertUserRequired checks if the required fields are not zero-ed +func AssertUserRequired(obj User) error { + elements := map[string]interface{}{ + "deepSliceModel": obj.DeepSliceModel, + } + for name, el := range elements { + if isZero := IsZeroValue(el); isZero { + return &RequiredError{Field: name} + } + } + + if obj.DeepSliceModel != nil { + if err := AssertRecurseInterfaceRequired(*obj.DeepSliceModel, AssertTagRequired); err != nil { + return err + } + } + if err := AssertRecurseInterfaceRequired(obj.DeepSliceMap, AssertAnObjectRequired); err != nil { + return err + } + return nil +} + +// AssertUserConstraints checks if the values respects the defined constraints +func AssertUserConstraints(obj User) error { + return nil +} diff --git a/samples/openapi3/server/petstore/go/go-petstore/go/routers.go b/samples/openapi3/server/petstore/go/go-petstore/go/routers.go new file mode 100644 index 00000000000..af326677bf4 --- /dev/null +++ b/samples/openapi3/server/petstore/go/go-petstore/go/routers.go @@ -0,0 +1,299 @@ +/* + * OpenAPI Petstore + * + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package petstoreserver + +import ( + "encoding/json" + "errors" + "github.com/go-chi/chi/v5" + "github.com/go-chi/chi/v5/middleware" + "io/ioutil" + "mime/multipart" + "net/http" + "os" + "strconv" + "strings" +) + +// A Route defines the parameters for an api endpoint +type Route struct { + Method string + Pattern string + HandlerFunc http.HandlerFunc +} + +// Routes is a map of defined api endpoints +type Routes map[string]Route + +// Router defines the required methods for retrieving api routes +type Router interface { + Routes() Routes +} + +const errMsgRequiredMissing = "required parameter is missing" +const errMsgMinValueConstraint = "provided parameter is not respecting minimum value constraint" +const errMsgMaxValueConstraint = "provided parameter is not respecting maximum value constraint" + +// NewRouter creates a new router for any number of api routers +func NewRouter(routers ...Router) chi.Router { + router := chi.NewRouter() + router.Use(middleware.Logger) + for _, api := range routers { + for _, route := range api.Routes() { + var handler http.Handler + handler = route.HandlerFunc + router.Method(route.Method, route.Pattern, handler) + } + } + + return router +} + +// EncodeJSONResponse uses the json encoder to write an interface to the http response with an optional status code +func EncodeJSONResponse(i interface{}, status *int, headers map[string][]string, w http.ResponseWriter) error { + wHeader := w.Header() + for key, values := range headers { + for _, value := range values { + wHeader.Add(key, value) + } + } + wHeader.Set("Content-Type", "application/json; charset=UTF-8") + if status != nil { + w.WriteHeader(*status) + } else { + w.WriteHeader(http.StatusOK) + } + + if i != nil { + return json.NewEncoder(w).Encode(i) + } + + return nil +} + +// ReadFormFileToTempFile reads file data from a request form and writes it to a temporary file +func ReadFormFileToTempFile(r *http.Request, key string) (*os.File, error) { + _, fileHeader, err := r.FormFile(key) + if err != nil { + return nil, err + } + + return readFileHeaderToTempFile(fileHeader) +} + +// ReadFormFilesToTempFiles reads files array data from a request form and writes it to a temporary files +func ReadFormFilesToTempFiles(r *http.Request, key string) ([]*os.File, error) { + if err := r.ParseMultipartForm(32 << 20); err != nil { + return nil, err + } + + files := make([]*os.File, 0, len(r.MultipartForm.File[key])) + + for _, fileHeader := range r.MultipartForm.File[key] { + file, err := readFileHeaderToTempFile(fileHeader) + if err != nil { + return nil, err + } + + files = append(files, file) + } + + return files, nil +} + +// readFileHeaderToTempFile reads multipart.FileHeader and writes it to a temporary file +func readFileHeaderToTempFile(fileHeader *multipart.FileHeader) (*os.File, error) { + formFile, err := fileHeader.Open() + if err != nil { + return nil, err + } + + defer formFile.Close() + + fileBytes, err := ioutil.ReadAll(formFile) + if err != nil { + return nil, err + } + + file, err := ioutil.TempFile("", fileHeader.Filename) + if err != nil { + return nil, err + } + + defer file.Close() + + file.Write(fileBytes) + + return file, nil +} + +type Number interface { + ~int32 | ~int64 | ~float32 | ~float64 +} + +type ParseString[T Number | string | bool] func(v string) (T, error) + +// parseFloat64 parses a string parameter to an float64. +func parseFloat64(param string) (float64, error) { + if param == "" { + return 0, nil + } + + return strconv.ParseFloat(param, 64) +} + +// parseFloat32 parses a string parameter to an float32. +func parseFloat32(param string) (float32, error) { + if param == "" { + return 0, nil + } + + v, err := strconv.ParseFloat(param, 32) + return float32(v), err +} + +// parseInt64 parses a string parameter to an int64. +func parseInt64(param string) (int64, error) { + if param == "" { + return 0, nil + } + + return strconv.ParseInt(param, 10, 64) +} + +// parseInt32 parses a string parameter to an int32. +func parseInt32(param string) (int32, error) { + if param == "" { + return 0, nil + } + + val, err := strconv.ParseInt(param, 10, 32) + return int32(val), err +} + +// parseBool parses a string parameter to an bool. +func parseBool(param string) (bool, error) { + if param == "" { + return false, nil + } + + return strconv.ParseBool(param) +} + +type Operation[T Number | string | bool] func(actual string) (T, bool, error) + +func WithRequire[T Number | string | bool](parse ParseString[T]) Operation[T] { + var empty T + return func(actual string) (T, bool, error) { + if actual == "" { + return empty, false, errors.New(errMsgRequiredMissing) + } + + v, err := parse(actual) + return v, false, err + } +} + +func WithDefaultOrParse[T Number | string | bool](def T, parse ParseString[T]) Operation[T] { + return func(actual string) (T, bool, error) { + if actual == "" { + return def, true, nil + } + + v, err := parse(actual) + return v, false, err + } +} + +func WithParse[T Number | string | bool](parse ParseString[T]) Operation[T] { + return func(actual string) (T, bool, error) { + v, err := parse(actual) + return v, false, err + } +} + +type Constraint[T Number | string | bool] func(actual T) error + +func WithMinimum[T Number](expected T) Constraint[T] { + return func(actual T) error { + if actual < expected { + return errors.New(errMsgMinValueConstraint) + } + + return nil + } +} + +func WithMaximum[T Number](expected T) Constraint[T] { + return func(actual T) error { + if actual > expected { + return errors.New(errMsgMaxValueConstraint) + } + + return nil + } +} + +// parseNumericParameter parses a numeric parameter to its respective type. +func parseNumericParameter[T Number](param string, fn Operation[T], checks ...Constraint[T]) (T, error) { + v, ok, err := fn(param) + if err != nil { + return 0, err + } + + if !ok { + for _, check := range checks { + if err := check(v); err != nil { + return 0, err + } + } + } + + return v, nil +} + +// parseBoolParameter parses a string parameter to a bool +func parseBoolParameter(param string, fn Operation[bool]) (bool, error) { + v, _, err := fn(param) + return v, err +} + +// parseNumericArrayParameter parses a string parameter containing array of values to its respective type. +func parseNumericArrayParameter[T Number](param, delim string, required bool, fn Operation[T], checks ...Constraint[T]) ([]T, error) { + if param == "" { + if required { + return nil, errors.New(errMsgRequiredMissing) + } + + return nil, nil + } + + str := strings.Split(param, delim) + values := make([]T, len(str)) + + for i, s := range str { + v, ok, err := fn(s) + if err != nil { + return nil, err + } + + if !ok { + for _, check := range checks { + if err := check(v); err != nil { + return nil, err + } + } + } + + values[i] = v + } + + return values, nil +} diff --git a/samples/openapi3/server/petstore/go/go-petstore/main.go b/samples/openapi3/server/petstore/go/go-petstore/main.go new file mode 100644 index 00000000000..c3153dbd8f9 --- /dev/null +++ b/samples/openapi3/server/petstore/go/go-petstore/main.go @@ -0,0 +1,34 @@ +/* + * OpenAPI Petstore + * + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package main + +import ( + "log" + "net/http" + + petstoreserver "github.com/GIT_USER_ID/GIT_REPO_ID/go" +) + +func main() { + log.Printf("Server started") + + PetAPIService := petstoreserver.NewPetAPIService() + PetAPIController := petstoreserver.NewPetAPIController(PetAPIService) + + StoreAPIService := petstoreserver.NewStoreAPIService() + StoreAPIController := petstoreserver.NewStoreAPIController(StoreAPIService) + + UserAPIService := petstoreserver.NewUserAPIService() + UserAPIController := petstoreserver.NewUserAPIController(UserAPIService) + + router := petstoreserver.NewRouter(PetAPIController, StoreAPIController, UserAPIController) + + log.Fatal(http.ListenAndServe(":8080", router)) +} diff --git a/samples/openapi3/server/petstore/go/go.mod b/samples/openapi3/server/petstore/go/go.mod new file mode 100644 index 00000000000..ffadfdb5bfa --- /dev/null +++ b/samples/openapi3/server/petstore/go/go.mod @@ -0,0 +1,17 @@ +module github.com/OpenAPITools/openapi-generator/samples/openapi3/server/petstore/go + +go 1.18 + +require ( + github.com/stretchr/testify v1.8.4 + go-petstore v0.0.0-00010101000000-000000000000 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-chi/chi/v5 v5.0.8 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace go-petstore => ./go-petstore diff --git a/samples/openapi3/server/petstore/go/go.sum b/samples/openapi3/server/petstore/go/go.sum new file mode 100644 index 00000000000..48c39e6cbba --- /dev/null +++ b/samples/openapi3/server/petstore/go/go.sum @@ -0,0 +1,12 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0= +github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/samples/server/petstore/go-api-server/.openapi-generator/FILES b/samples/server/petstore/go-api-server/.openapi-generator/FILES index 59b4003ddce..4c3a2a3a7c7 100644 --- a/samples/server/petstore/go-api-server/.openapi-generator/FILES +++ b/samples/server/petstore/go-api-server/.openapi-generator/FILES @@ -13,10 +13,13 @@ go/error.go go/helpers.go go/impl.go go/logger.go +go/model_an_object.go go/model_api_response.go go/model_category.go go/model_order.go +go/model_order_info.go go/model_pet.go +go/model_special_info.go go/model_tag.go go/model_user.go go/routers.go diff --git a/samples/server/petstore/go-api-server/api/openapi.yaml b/samples/server/petstore/go-api-server/api/openapi.yaml index a6128a433a5..cc433a6afd5 100644 --- a/samples/server/petstore/go-api-server/api/openapi.yaml +++ b/samples/server/petstore/go-api-server/api/openapi.yaml @@ -620,11 +620,44 @@ components: description: Pet object that needs to be added to the store required: true schemas: + OrderInfo: + description: An order info for a pets from the pet store + properties: + petId: + format: int64 + type: integer + quantity: + format: int32 + type: integer + shipDate: + format: date-time + type: string + title: Pet Order Info + type: object + xml: + name: OrderInfo + SpecialInfo: + description: An order info for a pets from the pet store + discriminator: + propertyName: type + properties: + promotion: + type: boolean + type: + type: string + title: Pet Order Info + type: object + xml: + name: OrderInfo Order: + allOf: + - $ref: '#/components/schemas/OrderInfo' + - $ref: '#/components/schemas/SpecialInfo' description: An order for a pets from the pet store example: petId: 6 quantity: 1 + comment: comment id: 0 shipDate: 2000-01-23T04:56:07.000+00:00 complete: false @@ -652,6 +685,11 @@ components: complete: default: false type: boolean + comment: + nullable: true + type: string + required: + - comment title: Pet Order type: object xml: @@ -661,6 +699,7 @@ components: example: name: name id: 6 + nullable: true properties: id: format: int64 @@ -680,7 +719,153 @@ components: password: password userStatus: 6 phone: phone + deepSliceModel: + - - - name: name + id: 1 + - name: name + id: 1 + - - name: name + id: 1 + - name: name + id: 1 + - - - name: name + id: 1 + - name: name + id: 1 + - - name: name + id: 1 + - name: name + id: 1 id: 0 + deepSliceMap: + - - tag: + name: name + id: 1 + Pet: + - photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + - photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + - tag: + name: name + id: 1 + Pet: + - photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + - photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + - - tag: + name: name + id: 1 + Pet: + - photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + - photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + - tag: + name: name + id: 1 + Pet: + - photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + - photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available email: email username: username properties: @@ -698,11 +883,34 @@ components: password: type: string phone: + nullable: true type: string userStatus: description: User Status format: int32 type: integer + deepSliceModel: + description: An array 1-deep. + items: + description: An array 2-deep. + items: + description: An array 3-deep. + items: + $ref: '#/components/schemas/Tag' + type: array + type: array + nullable: true + type: array + deepSliceMap: + description: An array 1-deep. + items: + description: An array 2-deep. + items: + $ref: '#/components/schemas/an_Object' + type: array + type: array + required: + - deepSliceModel title: a User type: object xml: @@ -751,6 +959,7 @@ components: photoUrls: items: type: string + nullable: true type: array xml: name: photoUrl @@ -758,6 +967,7 @@ components: tags: items: $ref: '#/components/schemas/Tag' + nullable: true type: array xml: name: tag @@ -812,6 +1022,51 @@ components: format: binary type: string type: object + an_Object: + description: An array 3-deep. + example: + tag: + name: name + id: 1 + Pet: + - photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + - photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + properties: + tag: + $ref: '#/components/schemas/Tag' + Pet: + description: An array of pet. + items: + $ref: '#/components/schemas/Pet' + type: array + title: an Object + type: object securitySchemes: petstore_auth: flows: diff --git a/samples/server/petstore/go-api-server/go/model_an_object.go b/samples/server/petstore/go-api-server/go/model_an_object.go new file mode 100644 index 00000000000..ece30644b87 --- /dev/null +++ b/samples/server/petstore/go-api-server/go/model_an_object.go @@ -0,0 +1,40 @@ +/* + * OpenAPI Petstore + * + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package petstoreserver + + + + +// AnObject - An array 3-deep. +type AnObject struct { + + Tag Tag `json:"tag,omitempty"` + + // An array of pet. + Pet []Pet `json:"Pet,omitempty"` +} + +// AssertAnObjectRequired checks if the required fields are not zero-ed +func AssertAnObjectRequired(obj AnObject) error { + if err := AssertTagRequired(obj.Tag); err != nil { + return err + } + for _, el := range obj.Pet { + if err := AssertPetRequired(el); err != nil { + return err + } + } + return nil +} + +// AssertAnObjectConstraints checks if the values respects the defined constraints +func AssertAnObjectConstraints(obj AnObject) error { + return nil +} diff --git a/samples/server/petstore/go-api-server/go/model_api_response.go b/samples/server/petstore/go-api-server/go/model_api_response.go index 0ef560396fd..795fed14f6e 100644 --- a/samples/server/petstore/go-api-server/go/model_api_response.go +++ b/samples/server/petstore/go-api-server/go/model_api_response.go @@ -10,10 +10,6 @@ package petstoreserver -import ( - "encoding/json" -) - // ApiResponse - Describes the result of uploading an image resource @@ -26,13 +22,6 @@ type ApiResponse struct { Message string `json:"message,omitempty"` } -// UnmarshalJSON sets *m to a copy of data while respecting defaults if specified. -func (m *ApiResponse) UnmarshalJSON(data []byte) error { - - type Alias ApiResponse // To avoid infinite recursion - return json.Unmarshal(data, (*Alias)(m)) -} - // AssertApiResponseRequired checks if the required fields are not zero-ed func AssertApiResponseRequired(obj ApiResponse) error { return nil diff --git a/samples/server/petstore/go-api-server/go/model_category.go b/samples/server/petstore/go-api-server/go/model_category.go index 1581493112a..e7c13aeaa9f 100644 --- a/samples/server/petstore/go-api-server/go/model_category.go +++ b/samples/server/petstore/go-api-server/go/model_category.go @@ -10,10 +10,6 @@ package petstoreserver -import ( - "encoding/json" -) - // Category - A category for a pet @@ -24,13 +20,6 @@ type Category struct { Name string `json:"name,omitempty"` } -// UnmarshalJSON sets *m to a copy of data while respecting defaults if specified. -func (m *Category) UnmarshalJSON(data []byte) error { - - type Alias Category // To avoid infinite recursion - return json.Unmarshal(data, (*Alias)(m)) -} - // AssertCategoryRequired checks if the required fields are not zero-ed func AssertCategoryRequired(obj Category) error { return nil diff --git a/samples/server/petstore/go-api-server/go/model_order.go b/samples/server/petstore/go-api-server/go/model_order.go index 1aa6b22e20f..8f712445efe 100644 --- a/samples/server/petstore/go-api-server/go/model_order.go +++ b/samples/server/petstore/go-api-server/go/model_order.go @@ -12,13 +12,13 @@ package petstoreserver import ( "time" - "encoding/json" ) // Order - An order for a pets from the pet store type Order struct { + SpecialInfo Id int64 `json:"id,omitempty"` @@ -32,18 +32,25 @@ type Order struct { Status string `json:"status,omitempty"` Complete bool `json:"complete,omitempty"` -} -// UnmarshalJSON sets *m to a copy of data while respecting defaults if specified. -func (m *Order) UnmarshalJSON(data []byte) error { - m.Complete = false - - type Alias Order // To avoid infinite recursion - return json.Unmarshal(data, (*Alias)(m)) + Comment *string `json:"comment"` } // AssertOrderRequired checks if the required fields are not zero-ed func AssertOrderRequired(obj Order) error { + elements := map[string]interface{}{ + "comment": obj.Comment, + } + for name, el := range elements { + if isZero := IsZeroValue(el); isZero { + return &RequiredError{Field: name} + } + } + + if err := AssertSpecialInfoRequired(obj.SpecialInfo); err != nil { + return err + } + return nil } diff --git a/samples/server/petstore/go-api-server/go/model_order_info.go b/samples/server/petstore/go-api-server/go/model_order_info.go new file mode 100644 index 00000000000..4426570b024 --- /dev/null +++ b/samples/server/petstore/go-api-server/go/model_order_info.go @@ -0,0 +1,37 @@ +/* + * OpenAPI Petstore + * + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package petstoreserver + + +import ( + "time" +) + + + +// OrderInfo - An order info for a pets from the pet store +type OrderInfo struct { + + PetId int64 `json:"petId,omitempty"` + + Quantity int32 `json:"quantity,omitempty"` + + ShipDate time.Time `json:"shipDate,omitempty"` +} + +// AssertOrderInfoRequired checks if the required fields are not zero-ed +func AssertOrderInfoRequired(obj OrderInfo) error { + return nil +} + +// AssertOrderInfoConstraints checks if the values respects the defined constraints +func AssertOrderInfoConstraints(obj OrderInfo) error { + return nil +} diff --git a/samples/server/petstore/go-api-server/go/model_pet.go b/samples/server/petstore/go-api-server/go/model_pet.go index 948533cd1a5..6226912d13f 100644 --- a/samples/server/petstore/go-api-server/go/model_pet.go +++ b/samples/server/petstore/go-api-server/go/model_pet.go @@ -10,10 +10,6 @@ package petstoreserver -import ( - "encoding/json" -) - // Pet - A pet for sale in the pet store @@ -21,26 +17,19 @@ type Pet struct { Id int64 `json:"id,omitempty"` - Category Category `json:"category,omitempty"` + Category *Category `json:"category,omitempty"` Name string `json:"name"` - PhotoUrls []string `json:"photoUrls"` + PhotoUrls *[]string `json:"photoUrls"` - Tags []Tag `json:"tags,omitempty"` + Tags *[]Tag `json:"tags,omitempty"` // pet status in the store // Deprecated Status string `json:"status,omitempty"` } -// UnmarshalJSON sets *m to a copy of data while respecting defaults if specified. -func (m *Pet) UnmarshalJSON(data []byte) error { - - type Alias Pet // To avoid infinite recursion - return json.Unmarshal(data, (*Alias)(m)) -} - // AssertPetRequired checks if the required fields are not zero-ed func AssertPetRequired(obj Pet) error { elements := map[string]interface{}{ @@ -53,14 +42,18 @@ func AssertPetRequired(obj Pet) error { } } - if err := AssertCategoryRequired(obj.Category); err != nil { - return err - } - for _, el := range obj.Tags { - if err := AssertTagRequired(el); err != nil { + if obj.Category != nil { + if err := AssertCategoryRequired(*obj.Category); err != nil { return err } } + if obj.Tags != nil { + for _, el := range *obj.Tags { + if err := AssertTagRequired(el); err != nil { + return err + } + } + } return nil } diff --git a/samples/server/petstore/go-api-server/go/model_special_info.go b/samples/server/petstore/go-api-server/go/model_special_info.go new file mode 100644 index 00000000000..e9eeebc5438 --- /dev/null +++ b/samples/server/petstore/go-api-server/go/model_special_info.go @@ -0,0 +1,31 @@ +/* + * OpenAPI Petstore + * + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package petstoreserver + + + + +// SpecialInfo - An order info for a pets from the pet store +type SpecialInfo struct { + + Promotion bool `json:"promotion,omitempty"` + + Type string `json:"type,omitempty"` +} + +// AssertSpecialInfoRequired checks if the required fields are not zero-ed +func AssertSpecialInfoRequired(obj SpecialInfo) error { + return nil +} + +// AssertSpecialInfoConstraints checks if the values respects the defined constraints +func AssertSpecialInfoConstraints(obj SpecialInfo) error { + return nil +} diff --git a/samples/server/petstore/go-api-server/go/model_tag.go b/samples/server/petstore/go-api-server/go/model_tag.go index 47073503db0..8b1a4facbae 100644 --- a/samples/server/petstore/go-api-server/go/model_tag.go +++ b/samples/server/petstore/go-api-server/go/model_tag.go @@ -10,10 +10,6 @@ package petstoreserver -import ( - "encoding/json" -) - // Tag - A tag for a pet @@ -24,13 +20,6 @@ type Tag struct { Name string `json:"name,omitempty"` } -// UnmarshalJSON sets *m to a copy of data while respecting defaults if specified. -func (m *Tag) UnmarshalJSON(data []byte) error { - - type Alias Tag // To avoid infinite recursion - return json.Unmarshal(data, (*Alias)(m)) -} - // AssertTagRequired checks if the required fields are not zero-ed func AssertTagRequired(obj Tag) error { return nil diff --git a/samples/server/petstore/go-api-server/go/model_user.go b/samples/server/petstore/go-api-server/go/model_user.go index 0021fe30bd7..1e0a432e8d4 100644 --- a/samples/server/petstore/go-api-server/go/model_user.go +++ b/samples/server/petstore/go-api-server/go/model_user.go @@ -10,10 +10,6 @@ package petstoreserver -import ( - "encoding/json" -) - // User - A User who is purchasing from the pet store @@ -31,21 +27,37 @@ type User struct { Password string `json:"password,omitempty"` - Phone string `json:"phone,omitempty"` + Phone *string `json:"phone,omitempty"` // User Status UserStatus int32 `json:"userStatus,omitempty"` -} -// UnmarshalJSON sets *m to a copy of data while respecting defaults if specified. -func (m *User) UnmarshalJSON(data []byte) error { + // An array 1-deep. + DeepSliceModel *[][][]Tag `json:"deepSliceModel"` - type Alias User // To avoid infinite recursion - return json.Unmarshal(data, (*Alias)(m)) + // An array 1-deep. + DeepSliceMap [][]AnObject `json:"deepSliceMap,omitempty"` } // AssertUserRequired checks if the required fields are not zero-ed func AssertUserRequired(obj User) error { + elements := map[string]interface{}{ + "deepSliceModel": obj.DeepSliceModel, + } + for name, el := range elements { + if isZero := IsZeroValue(el); isZero { + return &RequiredError{Field: name} + } + } + + if obj.DeepSliceModel != nil { + if err := AssertRecurseInterfaceRequired(*obj.DeepSliceModel, AssertTagRequired); err != nil { + return err + } + } + if err := AssertRecurseInterfaceRequired(obj.DeepSliceMap, AssertAnObjectRequired); err != nil { + return err + } return nil } diff --git a/samples/server/petstore/go-api-server/go/routers.go b/samples/server/petstore/go-api-server/go/routers.go index 8f2734893d0..1fb27970fdc 100644 --- a/samples/server/petstore/go-api-server/go/routers.go +++ b/samples/server/petstore/go-api-server/go/routers.go @@ -146,28 +146,48 @@ type ParseString[T Number | string | bool] func(v string) (T, error) // parseFloat64 parses a string parameter to an float64. func parseFloat64(param string) (float64, error) { + if param == "" { + return 0, nil + } + return strconv.ParseFloat(param, 64) } // parseFloat32 parses a string parameter to an float32. func parseFloat32(param string) (float32, error) { + if param == "" { + return 0, nil + } + v, err := strconv.ParseFloat(param, 32) return float32(v), err } // parseInt64 parses a string parameter to an int64. func parseInt64(param string) (int64, error) { + if param == "" { + return 0, nil + } + return strconv.ParseInt(param, 10, 64) } // parseInt32 parses a string parameter to an int32. func parseInt32(param string) (int32, error) { + if param == "" { + return 0, nil + } + val, err := strconv.ParseInt(param, 10, 32) return int32(val), err } // parseBool parses a string parameter to an bool. func parseBool(param string) (bool, error) { + if param == "" { + return false, nil + } + return strconv.ParseBool(param) } diff --git a/samples/server/petstore/go-chi-server/.openapi-generator/FILES b/samples/server/petstore/go-chi-server/.openapi-generator/FILES index 59b4003ddce..4c3a2a3a7c7 100644 --- a/samples/server/petstore/go-chi-server/.openapi-generator/FILES +++ b/samples/server/petstore/go-chi-server/.openapi-generator/FILES @@ -13,10 +13,13 @@ go/error.go go/helpers.go go/impl.go go/logger.go +go/model_an_object.go go/model_api_response.go go/model_category.go go/model_order.go +go/model_order_info.go go/model_pet.go +go/model_special_info.go go/model_tag.go go/model_user.go go/routers.go diff --git a/samples/server/petstore/go-chi-server/api/openapi.yaml b/samples/server/petstore/go-chi-server/api/openapi.yaml index 9a95adaefff..cc433a6afd5 100644 --- a/samples/server/petstore/go-chi-server/api/openapi.yaml +++ b/samples/server/petstore/go-chi-server/api/openapi.yaml @@ -451,6 +451,14 @@ paths: schema: type: string style: form + - description: The password for login in clear text + explode: true + in: query + name: boolean_test + required: false + schema: + type: boolean + style: form responses: "200": content: @@ -514,6 +522,14 @@ paths: schema: type: string style: simple + - description: boolean query parameter + explode: true + in: query + name: boolean_test + required: false + schema: + type: boolean + style: form responses: "400": description: Invalid username supplied @@ -604,11 +620,44 @@ components: description: Pet object that needs to be added to the store required: true schemas: + OrderInfo: + description: An order info for a pets from the pet store + properties: + petId: + format: int64 + type: integer + quantity: + format: int32 + type: integer + shipDate: + format: date-time + type: string + title: Pet Order Info + type: object + xml: + name: OrderInfo + SpecialInfo: + description: An order info for a pets from the pet store + discriminator: + propertyName: type + properties: + promotion: + type: boolean + type: + type: string + title: Pet Order Info + type: object + xml: + name: OrderInfo Order: + allOf: + - $ref: '#/components/schemas/OrderInfo' + - $ref: '#/components/schemas/SpecialInfo' description: An order for a pets from the pet store example: petId: 6 quantity: 1 + comment: comment id: 0 shipDate: 2000-01-23T04:56:07.000+00:00 complete: false @@ -636,6 +685,11 @@ components: complete: default: false type: boolean + comment: + nullable: true + type: string + required: + - comment title: Pet Order type: object xml: @@ -645,6 +699,7 @@ components: example: name: name id: 6 + nullable: true properties: id: format: int64 @@ -664,7 +719,153 @@ components: password: password userStatus: 6 phone: phone + deepSliceModel: + - - - name: name + id: 1 + - name: name + id: 1 + - - name: name + id: 1 + - name: name + id: 1 + - - - name: name + id: 1 + - name: name + id: 1 + - - name: name + id: 1 + - name: name + id: 1 id: 0 + deepSliceMap: + - - tag: + name: name + id: 1 + Pet: + - photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + - photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + - tag: + name: name + id: 1 + Pet: + - photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + - photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + - - tag: + name: name + id: 1 + Pet: + - photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + - photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + - tag: + name: name + id: 1 + Pet: + - photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + - photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available email: email username: username properties: @@ -682,11 +883,34 @@ components: password: type: string phone: + nullable: true type: string userStatus: description: User Status format: int32 type: integer + deepSliceModel: + description: An array 1-deep. + items: + description: An array 2-deep. + items: + description: An array 3-deep. + items: + $ref: '#/components/schemas/Tag' + type: array + type: array + nullable: true + type: array + deepSliceMap: + description: An array 1-deep. + items: + description: An array 2-deep. + items: + $ref: '#/components/schemas/an_Object' + type: array + type: array + required: + - deepSliceModel title: a User type: object xml: @@ -735,6 +959,7 @@ components: photoUrls: items: type: string + nullable: true type: array xml: name: photoUrl @@ -742,6 +967,7 @@ components: tags: items: $ref: '#/components/schemas/Tag' + nullable: true type: array xml: name: tag @@ -796,6 +1022,51 @@ components: format: binary type: string type: object + an_Object: + description: An array 3-deep. + example: + tag: + name: name + id: 1 + Pet: + - photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + - photoUrls: + - photoUrls + - photoUrls + name: doggie + id: 0 + category: + name: name + id: 6 + tags: + - name: name + id: 1 + - name: name + id: 1 + status: available + properties: + tag: + $ref: '#/components/schemas/Tag' + Pet: + description: An array of pet. + items: + $ref: '#/components/schemas/Pet' + type: array + title: an Object + type: object securitySchemes: petstore_auth: flows: diff --git a/samples/server/petstore/go-chi-server/go/api.go b/samples/server/petstore/go-chi-server/go/api.go index a01fcac929a..0f6f14dea75 100644 --- a/samples/server/petstore/go-chi-server/go/api.go +++ b/samples/server/petstore/go-chi-server/go/api.go @@ -92,9 +92,9 @@ type UserAPIServicer interface { CreateUser(context.Context, User) (ImplResponse, error) CreateUsersWithArrayInput(context.Context, []User) (ImplResponse, error) CreateUsersWithListInput(context.Context, []User) (ImplResponse, error) - DeleteUser(context.Context, string) (ImplResponse, error) + DeleteUser(context.Context, string, bool) (ImplResponse, error) GetUserByName(context.Context, string) (ImplResponse, error) - LoginUser(context.Context, string, string) (ImplResponse, error) + LoginUser(context.Context, string, string, bool) (ImplResponse, error) LogoutUser(context.Context) (ImplResponse, error) UpdateUser(context.Context, string, User) (ImplResponse, error) } diff --git a/samples/server/petstore/go-chi-server/go/api_user.go b/samples/server/petstore/go-chi-server/go/api_user.go index 9d8d85cd275..8cfdb13a4a6 100644 --- a/samples/server/petstore/go-chi-server/go/api_user.go +++ b/samples/server/petstore/go-chi-server/go/api_user.go @@ -172,8 +172,17 @@ func (c *UserAPIController) CreateUsersWithListInput(w http.ResponseWriter, r *h // DeleteUser - Delete user func (c *UserAPIController) DeleteUser(w http.ResponseWriter, r *http.Request) { + query := r.URL.Query() usernameParam := chi.URLParam(r, "username") - result, err := c.service.DeleteUser(r.Context(), usernameParam) + booleanTestParam, err := parseBoolParameter( + query.Get("boolean_test"), + WithParse[bool](parseBool), + ) + if err != nil { + w.WriteHeader(500) + return + } + result, err := c.service.DeleteUser(r.Context(), usernameParam, booleanTestParam) // If an error occurred, encode the error with the status code if err != nil { c.errorHandler(w, r, err, &result) @@ -201,7 +210,15 @@ func (c *UserAPIController) LoginUser(w http.ResponseWriter, r *http.Request) { query := r.URL.Query() usernameParam := query.Get("username") passwordParam := query.Get("password") - result, err := c.service.LoginUser(r.Context(), usernameParam, passwordParam) + booleanTestParam, err := parseBoolParameter( + query.Get("boolean_test"), + WithParse[bool](parseBool), + ) + if err != nil { + w.WriteHeader(500) + return + } + result, err := c.service.LoginUser(r.Context(), usernameParam, passwordParam, booleanTestParam) // If an error occurred, encode the error with the status code if err != nil { c.errorHandler(w, r, err, &result) diff --git a/samples/server/petstore/go-chi-server/go/api_user_service.go b/samples/server/petstore/go-chi-server/go/api_user_service.go index 390169be60d..05c9c06ef32 100644 --- a/samples/server/petstore/go-chi-server/go/api_user_service.go +++ b/samples/server/petstore/go-chi-server/go/api_user_service.go @@ -60,7 +60,7 @@ func (s *UserAPIService) CreateUsersWithListInput(ctx context.Context, user []Us } // DeleteUser - Delete user -func (s *UserAPIService) DeleteUser(ctx context.Context, username string) (ImplResponse, error) { +func (s *UserAPIService) DeleteUser(ctx context.Context, username string, booleanTest bool) (ImplResponse, error) { // TODO - update DeleteUser with the required logic for this service method. // Add api_user_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation. @@ -91,7 +91,7 @@ func (s *UserAPIService) GetUserByName(ctx context.Context, username string) (Im } // LoginUser - Logs user into the system -func (s *UserAPIService) LoginUser(ctx context.Context, username string, password string) (ImplResponse, error) { +func (s *UserAPIService) LoginUser(ctx context.Context, username string, password string, booleanTest bool) (ImplResponse, error) { // TODO - update LoginUser with the required logic for this service method. // Add api_user_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation. diff --git a/samples/server/petstore/go-chi-server/go/model_an_object.go b/samples/server/petstore/go-chi-server/go/model_an_object.go new file mode 100644 index 00000000000..ece30644b87 --- /dev/null +++ b/samples/server/petstore/go-chi-server/go/model_an_object.go @@ -0,0 +1,40 @@ +/* + * OpenAPI Petstore + * + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package petstoreserver + + + + +// AnObject - An array 3-deep. +type AnObject struct { + + Tag Tag `json:"tag,omitempty"` + + // An array of pet. + Pet []Pet `json:"Pet,omitempty"` +} + +// AssertAnObjectRequired checks if the required fields are not zero-ed +func AssertAnObjectRequired(obj AnObject) error { + if err := AssertTagRequired(obj.Tag); err != nil { + return err + } + for _, el := range obj.Pet { + if err := AssertPetRequired(el); err != nil { + return err + } + } + return nil +} + +// AssertAnObjectConstraints checks if the values respects the defined constraints +func AssertAnObjectConstraints(obj AnObject) error { + return nil +} diff --git a/samples/server/petstore/go-chi-server/go/model_api_response.go b/samples/server/petstore/go-chi-server/go/model_api_response.go index 0ef560396fd..795fed14f6e 100644 --- a/samples/server/petstore/go-chi-server/go/model_api_response.go +++ b/samples/server/petstore/go-chi-server/go/model_api_response.go @@ -10,10 +10,6 @@ package petstoreserver -import ( - "encoding/json" -) - // ApiResponse - Describes the result of uploading an image resource @@ -26,13 +22,6 @@ type ApiResponse struct { Message string `json:"message,omitempty"` } -// UnmarshalJSON sets *m to a copy of data while respecting defaults if specified. -func (m *ApiResponse) UnmarshalJSON(data []byte) error { - - type Alias ApiResponse // To avoid infinite recursion - return json.Unmarshal(data, (*Alias)(m)) -} - // AssertApiResponseRequired checks if the required fields are not zero-ed func AssertApiResponseRequired(obj ApiResponse) error { return nil diff --git a/samples/server/petstore/go-chi-server/go/model_category.go b/samples/server/petstore/go-chi-server/go/model_category.go index 1581493112a..e7c13aeaa9f 100644 --- a/samples/server/petstore/go-chi-server/go/model_category.go +++ b/samples/server/petstore/go-chi-server/go/model_category.go @@ -10,10 +10,6 @@ package petstoreserver -import ( - "encoding/json" -) - // Category - A category for a pet @@ -24,13 +20,6 @@ type Category struct { Name string `json:"name,omitempty"` } -// UnmarshalJSON sets *m to a copy of data while respecting defaults if specified. -func (m *Category) UnmarshalJSON(data []byte) error { - - type Alias Category // To avoid infinite recursion - return json.Unmarshal(data, (*Alias)(m)) -} - // AssertCategoryRequired checks if the required fields are not zero-ed func AssertCategoryRequired(obj Category) error { return nil diff --git a/samples/server/petstore/go-chi-server/go/model_order.go b/samples/server/petstore/go-chi-server/go/model_order.go index 1aa6b22e20f..8f712445efe 100644 --- a/samples/server/petstore/go-chi-server/go/model_order.go +++ b/samples/server/petstore/go-chi-server/go/model_order.go @@ -12,13 +12,13 @@ package petstoreserver import ( "time" - "encoding/json" ) // Order - An order for a pets from the pet store type Order struct { + SpecialInfo Id int64 `json:"id,omitempty"` @@ -32,18 +32,25 @@ type Order struct { Status string `json:"status,omitempty"` Complete bool `json:"complete,omitempty"` -} -// UnmarshalJSON sets *m to a copy of data while respecting defaults if specified. -func (m *Order) UnmarshalJSON(data []byte) error { - m.Complete = false - - type Alias Order // To avoid infinite recursion - return json.Unmarshal(data, (*Alias)(m)) + Comment *string `json:"comment"` } // AssertOrderRequired checks if the required fields are not zero-ed func AssertOrderRequired(obj Order) error { + elements := map[string]interface{}{ + "comment": obj.Comment, + } + for name, el := range elements { + if isZero := IsZeroValue(el); isZero { + return &RequiredError{Field: name} + } + } + + if err := AssertSpecialInfoRequired(obj.SpecialInfo); err != nil { + return err + } + return nil } diff --git a/samples/server/petstore/go-chi-server/go/model_order_info.go b/samples/server/petstore/go-chi-server/go/model_order_info.go new file mode 100644 index 00000000000..4426570b024 --- /dev/null +++ b/samples/server/petstore/go-chi-server/go/model_order_info.go @@ -0,0 +1,37 @@ +/* + * OpenAPI Petstore + * + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package petstoreserver + + +import ( + "time" +) + + + +// OrderInfo - An order info for a pets from the pet store +type OrderInfo struct { + + PetId int64 `json:"petId,omitempty"` + + Quantity int32 `json:"quantity,omitempty"` + + ShipDate time.Time `json:"shipDate,omitempty"` +} + +// AssertOrderInfoRequired checks if the required fields are not zero-ed +func AssertOrderInfoRequired(obj OrderInfo) error { + return nil +} + +// AssertOrderInfoConstraints checks if the values respects the defined constraints +func AssertOrderInfoConstraints(obj OrderInfo) error { + return nil +} diff --git a/samples/server/petstore/go-chi-server/go/model_pet.go b/samples/server/petstore/go-chi-server/go/model_pet.go index 948533cd1a5..6226912d13f 100644 --- a/samples/server/petstore/go-chi-server/go/model_pet.go +++ b/samples/server/petstore/go-chi-server/go/model_pet.go @@ -10,10 +10,6 @@ package petstoreserver -import ( - "encoding/json" -) - // Pet - A pet for sale in the pet store @@ -21,26 +17,19 @@ type Pet struct { Id int64 `json:"id,omitempty"` - Category Category `json:"category,omitempty"` + Category *Category `json:"category,omitempty"` Name string `json:"name"` - PhotoUrls []string `json:"photoUrls"` + PhotoUrls *[]string `json:"photoUrls"` - Tags []Tag `json:"tags,omitempty"` + Tags *[]Tag `json:"tags,omitempty"` // pet status in the store // Deprecated Status string `json:"status,omitempty"` } -// UnmarshalJSON sets *m to a copy of data while respecting defaults if specified. -func (m *Pet) UnmarshalJSON(data []byte) error { - - type Alias Pet // To avoid infinite recursion - return json.Unmarshal(data, (*Alias)(m)) -} - // AssertPetRequired checks if the required fields are not zero-ed func AssertPetRequired(obj Pet) error { elements := map[string]interface{}{ @@ -53,14 +42,18 @@ func AssertPetRequired(obj Pet) error { } } - if err := AssertCategoryRequired(obj.Category); err != nil { - return err - } - for _, el := range obj.Tags { - if err := AssertTagRequired(el); err != nil { + if obj.Category != nil { + if err := AssertCategoryRequired(*obj.Category); err != nil { return err } } + if obj.Tags != nil { + for _, el := range *obj.Tags { + if err := AssertTagRequired(el); err != nil { + return err + } + } + } return nil } diff --git a/samples/server/petstore/go-chi-server/go/model_special_info.go b/samples/server/petstore/go-chi-server/go/model_special_info.go new file mode 100644 index 00000000000..e9eeebc5438 --- /dev/null +++ b/samples/server/petstore/go-chi-server/go/model_special_info.go @@ -0,0 +1,31 @@ +/* + * OpenAPI Petstore + * + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package petstoreserver + + + + +// SpecialInfo - An order info for a pets from the pet store +type SpecialInfo struct { + + Promotion bool `json:"promotion,omitempty"` + + Type string `json:"type,omitempty"` +} + +// AssertSpecialInfoRequired checks if the required fields are not zero-ed +func AssertSpecialInfoRequired(obj SpecialInfo) error { + return nil +} + +// AssertSpecialInfoConstraints checks if the values respects the defined constraints +func AssertSpecialInfoConstraints(obj SpecialInfo) error { + return nil +} diff --git a/samples/server/petstore/go-chi-server/go/model_tag.go b/samples/server/petstore/go-chi-server/go/model_tag.go index 47073503db0..8b1a4facbae 100644 --- a/samples/server/petstore/go-chi-server/go/model_tag.go +++ b/samples/server/petstore/go-chi-server/go/model_tag.go @@ -10,10 +10,6 @@ package petstoreserver -import ( - "encoding/json" -) - // Tag - A tag for a pet @@ -24,13 +20,6 @@ type Tag struct { Name string `json:"name,omitempty"` } -// UnmarshalJSON sets *m to a copy of data while respecting defaults if specified. -func (m *Tag) UnmarshalJSON(data []byte) error { - - type Alias Tag // To avoid infinite recursion - return json.Unmarshal(data, (*Alias)(m)) -} - // AssertTagRequired checks if the required fields are not zero-ed func AssertTagRequired(obj Tag) error { return nil diff --git a/samples/server/petstore/go-chi-server/go/model_user.go b/samples/server/petstore/go-chi-server/go/model_user.go index 0021fe30bd7..1e0a432e8d4 100644 --- a/samples/server/petstore/go-chi-server/go/model_user.go +++ b/samples/server/petstore/go-chi-server/go/model_user.go @@ -10,10 +10,6 @@ package petstoreserver -import ( - "encoding/json" -) - // User - A User who is purchasing from the pet store @@ -31,21 +27,37 @@ type User struct { Password string `json:"password,omitempty"` - Phone string `json:"phone,omitempty"` + Phone *string `json:"phone,omitempty"` // User Status UserStatus int32 `json:"userStatus,omitempty"` -} -// UnmarshalJSON sets *m to a copy of data while respecting defaults if specified. -func (m *User) UnmarshalJSON(data []byte) error { + // An array 1-deep. + DeepSliceModel *[][][]Tag `json:"deepSliceModel"` - type Alias User // To avoid infinite recursion - return json.Unmarshal(data, (*Alias)(m)) + // An array 1-deep. + DeepSliceMap [][]AnObject `json:"deepSliceMap,omitempty"` } // AssertUserRequired checks if the required fields are not zero-ed func AssertUserRequired(obj User) error { + elements := map[string]interface{}{ + "deepSliceModel": obj.DeepSliceModel, + } + for name, el := range elements { + if isZero := IsZeroValue(el); isZero { + return &RequiredError{Field: name} + } + } + + if obj.DeepSliceModel != nil { + if err := AssertRecurseInterfaceRequired(*obj.DeepSliceModel, AssertTagRequired); err != nil { + return err + } + } + if err := AssertRecurseInterfaceRequired(obj.DeepSliceMap, AssertAnObjectRequired); err != nil { + return err + } return nil } diff --git a/samples/server/petstore/go-chi-server/go/routers.go b/samples/server/petstore/go-chi-server/go/routers.go index 2d69e3e03b7..af326677bf4 100644 --- a/samples/server/petstore/go-chi-server/go/routers.go +++ b/samples/server/petstore/go-chi-server/go/routers.go @@ -142,28 +142,48 @@ type ParseString[T Number | string | bool] func(v string) (T, error) // parseFloat64 parses a string parameter to an float64. func parseFloat64(param string) (float64, error) { + if param == "" { + return 0, nil + } + return strconv.ParseFloat(param, 64) } // parseFloat32 parses a string parameter to an float32. func parseFloat32(param string) (float32, error) { + if param == "" { + return 0, nil + } + v, err := strconv.ParseFloat(param, 32) return float32(v), err } // parseInt64 parses a string parameter to an int64. func parseInt64(param string) (int64, error) { + if param == "" { + return 0, nil + } + return strconv.ParseInt(param, 10, 64) } // parseInt32 parses a string parameter to an int32. func parseInt32(param string) (int32, error) { + if param == "" { + return 0, nil + } + val, err := strconv.ParseInt(param, 10, 32) return int32(val), err } // parseBool parses a string parameter to an bool. func parseBool(param string) (bool, error) { + if param == "" { + return false, nil + } + return strconv.ParseBool(param) } diff --git a/samples/server/petstore/go-server-required/go/model_an_object.go b/samples/server/petstore/go-server-required/go/model_an_object.go index f420aa2c80a..ece30644b87 100644 --- a/samples/server/petstore/go-server-required/go/model_an_object.go +++ b/samples/server/petstore/go-server-required/go/model_an_object.go @@ -10,10 +10,6 @@ package petstoreserver -import ( - "encoding/json" -) - // AnObject - An array 3-deep. @@ -25,13 +21,6 @@ type AnObject struct { Pet []Pet `json:"Pet,omitempty"` } -// UnmarshalJSON sets *m to a copy of data while respecting defaults if specified. -func (m *AnObject) UnmarshalJSON(data []byte) error { - - type Alias AnObject // To avoid infinite recursion - return json.Unmarshal(data, (*Alias)(m)) -} - // AssertAnObjectRequired checks if the required fields are not zero-ed func AssertAnObjectRequired(obj AnObject) error { if err := AssertTagRequired(obj.Tag); err != nil { diff --git a/samples/server/petstore/go-server-required/go/model_api_response.go b/samples/server/petstore/go-server-required/go/model_api_response.go index 0ef560396fd..795fed14f6e 100644 --- a/samples/server/petstore/go-server-required/go/model_api_response.go +++ b/samples/server/petstore/go-server-required/go/model_api_response.go @@ -10,10 +10,6 @@ package petstoreserver -import ( - "encoding/json" -) - // ApiResponse - Describes the result of uploading an image resource @@ -26,13 +22,6 @@ type ApiResponse struct { Message string `json:"message,omitempty"` } -// UnmarshalJSON sets *m to a copy of data while respecting defaults if specified. -func (m *ApiResponse) UnmarshalJSON(data []byte) error { - - type Alias ApiResponse // To avoid infinite recursion - return json.Unmarshal(data, (*Alias)(m)) -} - // AssertApiResponseRequired checks if the required fields are not zero-ed func AssertApiResponseRequired(obj ApiResponse) error { return nil diff --git a/samples/server/petstore/go-server-required/go/model_category.go b/samples/server/petstore/go-server-required/go/model_category.go index 1581493112a..e7c13aeaa9f 100644 --- a/samples/server/petstore/go-server-required/go/model_category.go +++ b/samples/server/petstore/go-server-required/go/model_category.go @@ -10,10 +10,6 @@ package petstoreserver -import ( - "encoding/json" -) - // Category - A category for a pet @@ -24,13 +20,6 @@ type Category struct { Name string `json:"name,omitempty"` } -// UnmarshalJSON sets *m to a copy of data while respecting defaults if specified. -func (m *Category) UnmarshalJSON(data []byte) error { - - type Alias Category // To avoid infinite recursion - return json.Unmarshal(data, (*Alias)(m)) -} - // AssertCategoryRequired checks if the required fields are not zero-ed func AssertCategoryRequired(obj Category) error { return nil diff --git a/samples/server/petstore/go-server-required/go/model_order.go b/samples/server/petstore/go-server-required/go/model_order.go index ca53e1fec03..a736aeb3e24 100644 --- a/samples/server/petstore/go-server-required/go/model_order.go +++ b/samples/server/petstore/go-server-required/go/model_order.go @@ -12,7 +12,6 @@ package petstoreserver import ( "time" - "encoding/json" ) @@ -37,14 +36,6 @@ type Order struct { ShipDate time.Time `json:"shipDate,omitempty"` } -// UnmarshalJSON sets *m to a copy of data while respecting defaults if specified. -func (m *Order) UnmarshalJSON(data []byte) error { - m.Complete = false - - type Alias Order // To avoid infinite recursion - return json.Unmarshal(data, (*Alias)(m)) -} - // AssertOrderRequired checks if the required fields are not zero-ed func AssertOrderRequired(obj Order) error { elements := map[string]interface{}{ diff --git a/samples/server/petstore/go-server-required/go/model_order_info.go b/samples/server/petstore/go-server-required/go/model_order_info.go index b5ec2eeaf0b..4426570b024 100644 --- a/samples/server/petstore/go-server-required/go/model_order_info.go +++ b/samples/server/petstore/go-server-required/go/model_order_info.go @@ -12,7 +12,6 @@ package petstoreserver import ( "time" - "encoding/json" ) @@ -27,13 +26,6 @@ type OrderInfo struct { ShipDate time.Time `json:"shipDate,omitempty"` } -// UnmarshalJSON sets *m to a copy of data while respecting defaults if specified. -func (m *OrderInfo) UnmarshalJSON(data []byte) error { - - type Alias OrderInfo // To avoid infinite recursion - return json.Unmarshal(data, (*Alias)(m)) -} - // AssertOrderInfoRequired checks if the required fields are not zero-ed func AssertOrderInfoRequired(obj OrderInfo) error { return nil diff --git a/samples/server/petstore/go-server-required/go/model_pet.go b/samples/server/petstore/go-server-required/go/model_pet.go index 9db44bec4e3..1d2c85d5423 100644 --- a/samples/server/petstore/go-server-required/go/model_pet.go +++ b/samples/server/petstore/go-server-required/go/model_pet.go @@ -10,10 +10,6 @@ package petstoreserver -import ( - "encoding/json" -) - // Pet - A pet for sale in the pet store @@ -33,13 +29,6 @@ type Pet struct { Status string `json:"status,omitempty"` } -// UnmarshalJSON sets *m to a copy of data while respecting defaults if specified. -func (m *Pet) UnmarshalJSON(data []byte) error { - - type Alias Pet // To avoid infinite recursion - return json.Unmarshal(data, (*Alias)(m)) -} - // AssertPetRequired checks if the required fields are not zero-ed func AssertPetRequired(obj Pet) error { elements := map[string]interface{}{ diff --git a/samples/server/petstore/go-server-required/go/model_special_info.go b/samples/server/petstore/go-server-required/go/model_special_info.go index 9b03b1feb17..e9eeebc5438 100644 --- a/samples/server/petstore/go-server-required/go/model_special_info.go +++ b/samples/server/petstore/go-server-required/go/model_special_info.go @@ -10,10 +10,6 @@ package petstoreserver -import ( - "encoding/json" -) - // SpecialInfo - An order info for a pets from the pet store @@ -24,13 +20,6 @@ type SpecialInfo struct { Type string `json:"type,omitempty"` } -// UnmarshalJSON sets *m to a copy of data while respecting defaults if specified. -func (m *SpecialInfo) UnmarshalJSON(data []byte) error { - - type Alias SpecialInfo // To avoid infinite recursion - return json.Unmarshal(data, (*Alias)(m)) -} - // AssertSpecialInfoRequired checks if the required fields are not zero-ed func AssertSpecialInfoRequired(obj SpecialInfo) error { return nil diff --git a/samples/server/petstore/go-server-required/go/model_tag.go b/samples/server/petstore/go-server-required/go/model_tag.go index 47073503db0..8b1a4facbae 100644 --- a/samples/server/petstore/go-server-required/go/model_tag.go +++ b/samples/server/petstore/go-server-required/go/model_tag.go @@ -10,10 +10,6 @@ package petstoreserver -import ( - "encoding/json" -) - // Tag - A tag for a pet @@ -24,13 +20,6 @@ type Tag struct { Name string `json:"name,omitempty"` } -// UnmarshalJSON sets *m to a copy of data while respecting defaults if specified. -func (m *Tag) UnmarshalJSON(data []byte) error { - - type Alias Tag // To avoid infinite recursion - return json.Unmarshal(data, (*Alias)(m)) -} - // AssertTagRequired checks if the required fields are not zero-ed func AssertTagRequired(obj Tag) error { return nil diff --git a/samples/server/petstore/go-server-required/go/model_user.go b/samples/server/petstore/go-server-required/go/model_user.go index 95a33011498..1e0a432e8d4 100644 --- a/samples/server/petstore/go-server-required/go/model_user.go +++ b/samples/server/petstore/go-server-required/go/model_user.go @@ -10,10 +10,6 @@ package petstoreserver -import ( - "encoding/json" -) - // User - A User who is purchasing from the pet store @@ -43,13 +39,6 @@ type User struct { DeepSliceMap [][]AnObject `json:"deepSliceMap,omitempty"` } -// UnmarshalJSON sets *m to a copy of data while respecting defaults if specified. -func (m *User) UnmarshalJSON(data []byte) error { - - type Alias User // To avoid infinite recursion - return json.Unmarshal(data, (*Alias)(m)) -} - // AssertUserRequired checks if the required fields are not zero-ed func AssertUserRequired(obj User) error { elements := map[string]interface{}{ diff --git a/samples/server/petstore/go-server-required/go/routers.go b/samples/server/petstore/go-server-required/go/routers.go index 2d69e3e03b7..af326677bf4 100644 --- a/samples/server/petstore/go-server-required/go/routers.go +++ b/samples/server/petstore/go-server-required/go/routers.go @@ -142,28 +142,48 @@ type ParseString[T Number | string | bool] func(v string) (T, error) // parseFloat64 parses a string parameter to an float64. func parseFloat64(param string) (float64, error) { + if param == "" { + return 0, nil + } + return strconv.ParseFloat(param, 64) } // parseFloat32 parses a string parameter to an float32. func parseFloat32(param string) (float32, error) { + if param == "" { + return 0, nil + } + v, err := strconv.ParseFloat(param, 32) return float32(v), err } // parseInt64 parses a string parameter to an int64. func parseInt64(param string) (int64, error) { + if param == "" { + return 0, nil + } + return strconv.ParseInt(param, 10, 64) } // parseInt32 parses a string parameter to an int32. func parseInt32(param string) (int32, error) { + if param == "" { + return 0, nil + } + val, err := strconv.ParseInt(param, 10, 32) return int32(val), err } // parseBool parses a string parameter to an bool. func parseBool(param string) (bool, error) { + if param == "" { + return false, nil + } + return strconv.ParseBool(param) }