From 44e3ccb0238e8fa159579c56b67913497bc74fd7 Mon Sep 17 00:00:00 2001 From: Ian Cubbon Date: Tue, 10 Oct 2023 12:41:03 -0700 Subject: [PATCH 1/9] Add support for Enums to be part of the Path and Query Supports optional Query Enums and Lists of Enums as well Add an example endpoint that covers the added scenarios Added an import mapping for the GoServerCodegen for "fmt" when a model is an enum. Expanded the Enum Model for the Go Server to have validation. Copied this logic from the Go Client Enum Model. --- .../codegen/languages/GoServerCodegen.java | 1 + .../go-server/controller-api.mustache | 63 ++++++++++++++++- .../main/resources/go-server/model.mustache | 34 ++++++++- .../resources/3_0/go-server/petstore.yaml | 60 ++++++++++++++++ .../petstore/go/go-petstore/go/api_pet.go | 10 ++- .../go-api-server/.openapi-generator/FILES | 2 + .../petstore/go-api-server/api/openapi.yaml | 62 ++++++++++++++++ .../server/petstore/go-api-server/go/api.go | 2 + .../petstore/go-api-server/go/api_pet.go | 52 +++++++++++++- .../go-api-server/go/api_pet_service.go | 14 ++++ .../petstore/go-api-server/go/model_gender.go | 64 +++++++++++++++++ .../go-api-server/go/model_species.go | 70 +++++++++++++++++++ .../go-chi-server/.openapi-generator/FILES | 2 + .../petstore/go-chi-server/api/openapi.yaml | 62 ++++++++++++++++ .../server/petstore/go-chi-server/go/api.go | 2 + .../petstore/go-chi-server/go/api_pet.go | 51 +++++++++++++- .../go-chi-server/go/api_pet_service.go | 14 ++++ .../petstore/go-chi-server/go/model_gender.go | 64 +++++++++++++++++ .../go-chi-server/go/model_species.go | 70 +++++++++++++++++++ 19 files changed, 689 insertions(+), 10 deletions(-) create mode 100644 samples/server/petstore/go-api-server/go/model_gender.go create mode 100644 samples/server/petstore/go-api-server/go/model_species.go create mode 100644 samples/server/petstore/go-chi-server/go/model_gender.go create mode 100644 samples/server/petstore/go-chi-server/go/model_species.go 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 97deeb584425..fff4b41bb7ab 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 @@ -301,6 +301,7 @@ public ModelsMap postProcessModels(ModelsMap objs) { CodegenModel model = m.getModel(); if (model.isEnum) { + imports.add(createMapping("import", "fmt")); continue; } diff --git a/modules/openapi-generator/src/main/resources/go-server/controller-api.mustache b/modules/openapi-generator/src/main/resources/go-server/controller-api.mustache index 00fec257d6e8..d6936fdb7dc9 100644 --- a/modules/openapi-generator/src/main/resources/go-server/controller-api.mustache +++ b/modules/openapi-generator/src/main/resources/go-server/controller-api.mustache @@ -173,7 +173,17 @@ func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Re {{^isDouble}} {{^isLong}} {{^isInteger}} + {{^isEnumOrRef}} {{paramName}}Param := {{#routers}}{{#mux}}params["{{baseName}}"]{{/mux}}{{#chi}}chi.URLParam(r, "{{baseName}}"){{/chi}}{{/routers}} + {{/isEnumOrRef}} + {{#isEnumOrRef}} + {{paramName}}ParamPtr, err := New{{dataType}}FromValue({{#routers}}{{#mux}}params["{{baseName}}"]{{/mux}}{{#chi}}chi.URLParam(r, "{{baseName}}"){{/chi}}{{/routers}}) + if err != nil { + c.errorHandler(w, r, &ParsingError{Err: err}, nil) + return + } + {{paramName}}Param := *{{paramName}}ParamPtr + {{/isEnumOrRef}} {{/isInteger}} {{/isLong}} {{/isDouble}} @@ -329,7 +339,25 @@ func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Re {{^items.isDouble}} {{^items.isLong}} {{^items.isInteger}} - {{paramName}}Param := strings.Split(query.Get("{{baseName}}"), ",") + {{^items.isEnumRef}} + var {{paramName}}Param [] string + if query.Has("{{baseName}}") { + {{paramName}}Param = strings.Split(query.Get("{{baseName}}"), ",") + } + {{/items.isEnumRef}} + {{#items.isEnumRef}} + var {{paramName}}Param []{{items.dataType}} + if query.Has("{{baseName}}") { + for _, param := range strings.Split(query.Get("{{baseName}}"), ",") { + paramEnum, err := New{{items.dataType}}FromValue(param) + if err != nil { + c.errorHandler(w, r, &ParsingError{Err: err}, nil) + return + } + {{paramName}}Param = append({{paramName}}Param, *paramEnum) + } + } + {{/items.isEnumRef}} {{/items.isInteger}} {{/items.isLong}} {{/items.isDouble}} @@ -344,13 +372,42 @@ func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Re {{^isBoolean}} {{^isArray}} {{#defaultValue}} - {{paramName}}Param := "{{defaultValue}}" if query.Has("{{baseName}}") { - {{paramName}}Param = query.Get("{{baseName}}") + {{paramName}}Param := {{^isString}}{{dataType}}( {{/isString}}query.Get("{{baseName}}"){{^isString}} ){{/isString}} } {{/defaultValue}} {{^defaultValue}} + {{^required}} + var {{paramName}}Param {{dataType}} + if query.Has("{{baseName}}") { + {{^isEnumOrRef}} + param := query.Get("{{baseName}}") + {{paramName}}Param = ¶m + {{/isEnumOrRef}} + {{#isEnumOrRef}} + var err error + {{paramName}}ParamPtr, err := New{{dataType}}FromValue(query.Get("{{baseName}}")) + if err != nil { + c.errorHandler(w, r, &ParsingError{Err: err}, nil) + return + } + {{paramName}}Param = *{{paramName}}ParamPtr + {{/isEnumOrRef}} + } + {{/required}} + {{#required}} + {{^isEnumOrRef}} {{paramName}}Param := query.Get("{{baseName}}") + {{/isEnumOrRef}} + {{#isEnumOrRef}} + {{paramName}}ParamPtr, err := New{{dataType}}FromValue(query.Get("{{baseName}}")) + if err != nil { + c.errorHandler(w, r, &ParsingError{Err: err}, nil) + return + } + {{paramName}}Param := *{{paramName}}ParamPtr + {{/isEnumOrRef}} + {{/required}} {{/defaultValue}} {{/isArray}} {{/isBoolean}} 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 f94a100a1913..f3704a7f08ca 100644 --- a/modules/openapi-generator/src/main/resources/go-server/model.mustache +++ b/modules/openapi-generator/src/main/resources/go-server/model.mustache @@ -17,7 +17,39 @@ const ( {{#enumClassPrefix}}{{{classname.toUpperCase}}}_{{/enumClassPrefix}}{{name}} {{{classname}}} = {{{value}}} {{/enumVars}} {{/allowableValues}} -){{/isEnum}}{{^isEnum}}{{#description}} +) + +// All allowed values of {{{classname}}} enum +var Allowed{{{classname}}}EnumValues = []{{{classname}}}{ + {{#allowableValues}} + {{#enumVars}} + {{{value}}}, + {{/enumVars}} + {{/allowableValues}} +} + +// IsValid return true if the value is valid for the enum, false otherwise +func (v {{{classname}}}) IsValid() bool { + for _, existing := range Allowed{{{classname}}}EnumValues { + if existing == v { + return true + } + } + return false +} + +// New{{{classname}}}FromValue returns a pointer to a valid {{{classname}}} +// for the value passed as argument, or an error if the value passed is not allowed by the enum +func New{{{classname}}}FromValue(v {{{format}}}{{^format}}{{dataType}}{{/format}}) (*{{{classname}}}, error) { + ev := {{{classname}}}(v) + if ev.IsValid() { + return &ev, nil + } else { + return nil, fmt.Errorf("invalid value '%v' for {{{classname}}}: valid values are %v", v, Allowed{{{classname}}}EnumValues) + } +} + +{{/isEnum}}{{^isEnum}}{{#description}} // {{classname}} - {{{description}}}{{/description}} type {{classname}} struct { {{#parent}} 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 fce2c52cbde4..2910b7abf7ec 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 @@ -157,6 +157,52 @@ paths: - petstore_auth: - 'read:pets' deprecated: true + '/pet/filterPets/{gender}': + get: + tags: + - pet + summary: Finds Pets + operationId: filterPetsByCategory + parameters: + - name: gender + in: path + required: true + schema: + $ref: '#/components/schemas/Gender' + - name: species + in: query + description: Species to filter by + required: true + style: form + explode: false + schema: + $ref: '#/components/schemas/Species' + - name: notSpecies + in: query + description: Species to omit from results + required: false + style: form + explode: false + schema: + type: array + items: + $ref: '#/components/schemas/Species' + responses: + '200': + description: successful operation + content: + application/xml: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + '400': + description: Invalid species value '/pet/{petId}': get: tags: @@ -810,6 +856,20 @@ components: - sold xml: name: Pet + Species: + title: The species of a pet + type: string + enum: + - cat + - dog + - fish + - goat + - pig + Gender: + type: string + enum: + - male + - female ApiResponse: title: An uploaded response description: Describes the result of uploading an image resource 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 index 0efd81a77e9f..c9f3e6042b39 100644 --- a/samples/openapi3/server/petstore/go/go-petstore/go/api_pet.go +++ b/samples/openapi3/server/petstore/go/go-petstore/go/api_pet.go @@ -144,7 +144,10 @@ func (c *PetAPIController) DeletePet(w http.ResponseWriter, r *http.Request) { // 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"), ",") + var statusParam [] string + if query.Has("status") { + 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 { @@ -159,7 +162,10 @@ func (c *PetAPIController) FindPetsByStatus(w http.ResponseWriter, r *http.Reque // Deprecated func (c *PetAPIController) FindPetsByTags(w http.ResponseWriter, r *http.Request) { query := r.URL.Query() - tagsParam := strings.Split(query.Get("tags"), ",") + var tagsParam [] string + if query.Has("tags") { + 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 { diff --git a/samples/server/petstore/go-api-server/.openapi-generator/FILES b/samples/server/petstore/go-api-server/.openapi-generator/FILES index 4c3a2a3a7c74..2e3c628098c4 100644 --- a/samples/server/petstore/go-api-server/.openapi-generator/FILES +++ b/samples/server/petstore/go-api-server/.openapi-generator/FILES @@ -16,10 +16,12 @@ go/logger.go go/model_an_object.go go/model_api_response.go go/model_category.go +go/model_gender.go go/model_order.go go/model_order_info.go go/model_pet.go go/model_special_info.go +go/model_species.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 cc433a6afd59..678c2a43f77a 100644 --- a/samples/server/petstore/go-api-server/api/openapi.yaml +++ b/samples/server/petstore/go-api-server/api/openapi.yaml @@ -158,6 +158,54 @@ paths: summary: Finds Pets by tags tags: - pet + /pet/filterPets/{gender}: + get: + operationId: filterPetsByCategory + parameters: + - explode: false + in: path + name: gender + required: true + schema: + $ref: '#/components/schemas/Gender' + style: simple + - description: Species to filter by + explode: false + in: query + name: species + required: true + schema: + $ref: '#/components/schemas/Species' + style: form + - description: Species to omit from results + explode: false + in: query + name: notSpecies + required: false + schema: + items: + $ref: '#/components/schemas/Species' + 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 species value + summary: Finds Pets + tags: + - pet /pet/{petId}: delete: description: "" @@ -987,6 +1035,20 @@ components: type: object xml: name: Pet + Species: + enum: + - cat + - dog + - fish + - goat + - pig + title: The species of a pet + type: string + Gender: + enum: + - male + - female + type: string ApiResponse: description: Describes the result of uploading an image resource example: diff --git a/samples/server/petstore/go-api-server/go/api.go b/samples/server/petstore/go-api-server/go/api.go index 0f6f14dea75f..b37706688dff 100644 --- a/samples/server/petstore/go-api-server/go/api.go +++ b/samples/server/petstore/go-api-server/go/api.go @@ -23,6 +23,7 @@ import ( type PetAPIRouter interface { AddPet(http.ResponseWriter, *http.Request) DeletePet(http.ResponseWriter, *http.Request) + FilterPetsByCategory(http.ResponseWriter, *http.Request) FindPetsByStatus(http.ResponseWriter, *http.Request) // Deprecated FindPetsByTags(http.ResponseWriter, *http.Request) @@ -62,6 +63,7 @@ type UserAPIRouter interface { type PetAPIServicer interface { AddPet(context.Context, Pet) (ImplResponse, error) DeletePet(context.Context, int64, string) (ImplResponse, error) + FilterPetsByCategory(context.Context, Gender, Species, []Species) (ImplResponse, error) FindPetsByStatus(context.Context, []string) (ImplResponse, error) // Deprecated FindPetsByTags(context.Context, []string) (ImplResponse, error) diff --git a/samples/server/petstore/go-api-server/go/api_pet.go b/samples/server/petstore/go-api-server/go/api_pet.go index 0161ba41d6cf..fc96fa96047d 100644 --- a/samples/server/petstore/go-api-server/go/api_pet.go +++ b/samples/server/petstore/go-api-server/go/api_pet.go @@ -60,6 +60,11 @@ func (c *PetAPIController) Routes() Routes { "/v2/pet/{petId}", c.DeletePet, }, + "FilterPetsByCategory": Route{ + strings.ToUpper("Get"), + "/v2/pet/filterPets/{gender}", + c.FilterPetsByCategory, + }, "FindPetsByStatus": Route{ strings.ToUpper("Get"), "/v2/pet/findByStatus", @@ -142,10 +147,50 @@ func (c *PetAPIController) DeletePet(w http.ResponseWriter, r *http.Request) { EncodeJSONResponse(result.Body, &result.Code, result.Headers, w) } +// FilterPetsByCategory - Finds Pets +func (c *PetAPIController) FilterPetsByCategory(w http.ResponseWriter, r *http.Request) { + params := mux.Vars(r) + query := r.URL.Query() + genderParamPtr, err := NewGenderFromValue(params["gender"]) + if err != nil { + c.errorHandler(w, r, &ParsingError{Err: err}, nil) + return + } + genderParam := *genderParamPtr + speciesParamPtr, err := NewSpeciesFromValue(query.Get("species")) + if err != nil { + c.errorHandler(w, r, &ParsingError{Err: err}, nil) + return + } + speciesParam := *speciesParamPtr + var notSpeciesParam []Species + if query.Has("notSpecies") { + for _, param := range strings.Split(query.Get("notSpecies"), ",") { + paramEnum, err := NewSpeciesFromValue(param) + if err != nil { + c.errorHandler(w, r, &ParsingError{Err: err}, nil) + return + } + notSpeciesParam = append(notSpeciesParam, *paramEnum) + } + } + result, err := c.service.FilterPetsByCategory(r.Context(), genderParam, speciesParam, notSpeciesParam) + // 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"), ",") + var statusParam [] string + if query.Has("status") { + 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 { @@ -160,7 +205,10 @@ func (c *PetAPIController) FindPetsByStatus(w http.ResponseWriter, r *http.Reque // Deprecated func (c *PetAPIController) FindPetsByTags(w http.ResponseWriter, r *http.Request) { query := r.URL.Query() - tagsParam := strings.Split(query.Get("tags"), ",") + var tagsParam [] string + if query.Has("tags") { + 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 { diff --git a/samples/server/petstore/go-api-server/go/api_pet_service.go b/samples/server/petstore/go-api-server/go/api_pet_service.go index bda4cd897526..38f7ba58655d 100644 --- a/samples/server/petstore/go-api-server/go/api_pet_service.go +++ b/samples/server/petstore/go-api-server/go/api_pet_service.go @@ -52,6 +52,20 @@ func (s *PetAPIService) DeletePet(ctx context.Context, petId int64, apiKey strin return Response(http.StatusNotImplemented, nil), errors.New("DeletePet method not implemented") } +// FilterPetsByCategory - Finds Pets +func (s *PetAPIService) FilterPetsByCategory(ctx context.Context, gender Gender, species Species, notSpecies []Species) (ImplResponse, error) { + // TODO - update FilterPetsByCategory 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("FilterPetsByCategory 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. diff --git a/samples/server/petstore/go-api-server/go/model_gender.go b/samples/server/petstore/go-api-server/go/model_gender.go new file mode 100644 index 000000000000..58b1dcb6ecbc --- /dev/null +++ b/samples/server/petstore/go-api-server/go/model_gender.go @@ -0,0 +1,64 @@ +/* + * 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 ( + "fmt" +) + + + +type Gender string + +// List of Gender +const ( + MALE Gender = "male" + FEMALE Gender = "female" +) + +// All allowed values of Gender enum +var AllowedGenderEnumValues = []Gender{ + "male", + "female", +} + +// IsValid return true if the value is valid for the enum, false otherwise +func (v Gender) IsValid() bool { + for _, existing := range AllowedGenderEnumValues { + if existing == v { + return true + } + } + return false +} + +// NewGenderFromValue returns a pointer to a valid Gender +// for the value passed as argument, or an error if the value passed is not allowed by the enum +func NewGenderFromValue(v string) (*Gender, error) { + ev := Gender(v) + if ev.IsValid() { + return &ev, nil + } else { + return nil, fmt.Errorf("invalid value '%v' for Gender: valid values are %v", v, AllowedGenderEnumValues) + } +} + + + +// AssertGenderRequired checks if the required fields are not zero-ed +func AssertGenderRequired(obj Gender) error { + return nil +} + +// AssertGenderConstraints checks if the values respects the defined constraints +func AssertGenderConstraints(obj Gender) error { + return nil +} diff --git a/samples/server/petstore/go-api-server/go/model_species.go b/samples/server/petstore/go-api-server/go/model_species.go new file mode 100644 index 000000000000..4a3cd280b219 --- /dev/null +++ b/samples/server/petstore/go-api-server/go/model_species.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 ( + "fmt" +) + + + +type Species string + +// List of Species +const ( + CAT Species = "cat" + DOG Species = "dog" + FISH Species = "fish" + GOAT Species = "goat" + PIG Species = "pig" +) + +// All allowed values of Species enum +var AllowedSpeciesEnumValues = []Species{ + "cat", + "dog", + "fish", + "goat", + "pig", +} + +// IsValid return true if the value is valid for the enum, false otherwise +func (v Species) IsValid() bool { + for _, existing := range AllowedSpeciesEnumValues { + if existing == v { + return true + } + } + return false +} + +// NewSpeciesFromValue returns a pointer to a valid Species +// for the value passed as argument, or an error if the value passed is not allowed by the enum +func NewSpeciesFromValue(v string) (*Species, error) { + ev := Species(v) + if ev.IsValid() { + return &ev, nil + } else { + return nil, fmt.Errorf("invalid value '%v' for Species: valid values are %v", v, AllowedSpeciesEnumValues) + } +} + + + +// AssertSpeciesRequired checks if the required fields are not zero-ed +func AssertSpeciesRequired(obj Species) error { + return nil +} + +// AssertSpeciesConstraints checks if the values respects the defined constraints +func AssertSpeciesConstraints(obj Species) error { + return nil +} diff --git a/samples/server/petstore/go-chi-server/.openapi-generator/FILES b/samples/server/petstore/go-chi-server/.openapi-generator/FILES index 4c3a2a3a7c74..2e3c628098c4 100644 --- a/samples/server/petstore/go-chi-server/.openapi-generator/FILES +++ b/samples/server/petstore/go-chi-server/.openapi-generator/FILES @@ -16,10 +16,12 @@ go/logger.go go/model_an_object.go go/model_api_response.go go/model_category.go +go/model_gender.go go/model_order.go go/model_order_info.go go/model_pet.go go/model_special_info.go +go/model_species.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 cc433a6afd59..678c2a43f77a 100644 --- a/samples/server/petstore/go-chi-server/api/openapi.yaml +++ b/samples/server/petstore/go-chi-server/api/openapi.yaml @@ -158,6 +158,54 @@ paths: summary: Finds Pets by tags tags: - pet + /pet/filterPets/{gender}: + get: + operationId: filterPetsByCategory + parameters: + - explode: false + in: path + name: gender + required: true + schema: + $ref: '#/components/schemas/Gender' + style: simple + - description: Species to filter by + explode: false + in: query + name: species + required: true + schema: + $ref: '#/components/schemas/Species' + style: form + - description: Species to omit from results + explode: false + in: query + name: notSpecies + required: false + schema: + items: + $ref: '#/components/schemas/Species' + 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 species value + summary: Finds Pets + tags: + - pet /pet/{petId}: delete: description: "" @@ -987,6 +1035,20 @@ components: type: object xml: name: Pet + Species: + enum: + - cat + - dog + - fish + - goat + - pig + title: The species of a pet + type: string + Gender: + enum: + - male + - female + type: string ApiResponse: description: Describes the result of uploading an image resource example: diff --git a/samples/server/petstore/go-chi-server/go/api.go b/samples/server/petstore/go-chi-server/go/api.go index 0f6f14dea75f..b37706688dff 100644 --- a/samples/server/petstore/go-chi-server/go/api.go +++ b/samples/server/petstore/go-chi-server/go/api.go @@ -23,6 +23,7 @@ import ( type PetAPIRouter interface { AddPet(http.ResponseWriter, *http.Request) DeletePet(http.ResponseWriter, *http.Request) + FilterPetsByCategory(http.ResponseWriter, *http.Request) FindPetsByStatus(http.ResponseWriter, *http.Request) // Deprecated FindPetsByTags(http.ResponseWriter, *http.Request) @@ -62,6 +63,7 @@ type UserAPIRouter interface { type PetAPIServicer interface { AddPet(context.Context, Pet) (ImplResponse, error) DeletePet(context.Context, int64, string) (ImplResponse, error) + FilterPetsByCategory(context.Context, Gender, Species, []Species) (ImplResponse, error) FindPetsByStatus(context.Context, []string) (ImplResponse, error) // Deprecated FindPetsByTags(context.Context, []string) (ImplResponse, error) diff --git a/samples/server/petstore/go-chi-server/go/api_pet.go b/samples/server/petstore/go-chi-server/go/api_pet.go index 0efd81a77e9f..3f6716ee91b6 100644 --- a/samples/server/petstore/go-chi-server/go/api_pet.go +++ b/samples/server/petstore/go-chi-server/go/api_pet.go @@ -60,6 +60,11 @@ func (c *PetAPIController) Routes() Routes { "/v2/pet/{petId}", c.DeletePet, }, + "FilterPetsByCategory": Route{ + strings.ToUpper("Get"), + "/v2/pet/filterPets/{gender}", + c.FilterPetsByCategory, + }, "FindPetsByStatus": Route{ strings.ToUpper("Get"), "/v2/pet/findByStatus", @@ -141,10 +146,49 @@ func (c *PetAPIController) DeletePet(w http.ResponseWriter, r *http.Request) { EncodeJSONResponse(result.Body, &result.Code, result.Headers, w) } +// FilterPetsByCategory - Finds Pets +func (c *PetAPIController) FilterPetsByCategory(w http.ResponseWriter, r *http.Request) { + query := r.URL.Query() + genderParamPtr, err := NewGenderFromValue(chi.URLParam(r, "gender")) + if err != nil { + c.errorHandler(w, r, &ParsingError{Err: err}, nil) + return + } + genderParam := *genderParamPtr + speciesParamPtr, err := NewSpeciesFromValue(query.Get("species")) + if err != nil { + c.errorHandler(w, r, &ParsingError{Err: err}, nil) + return + } + speciesParam := *speciesParamPtr + var notSpeciesParam []Species + if query.Has("notSpecies") { + for _, param := range strings.Split(query.Get("notSpecies"), ",") { + paramEnum, err := NewSpeciesFromValue(param) + if err != nil { + c.errorHandler(w, r, &ParsingError{Err: err}, nil) + return + } + notSpeciesParam = append(notSpeciesParam, *paramEnum) + } + } + result, err := c.service.FilterPetsByCategory(r.Context(), genderParam, speciesParam, notSpeciesParam) + // 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"), ",") + var statusParam [] string + if query.Has("status") { + 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 { @@ -159,7 +203,10 @@ func (c *PetAPIController) FindPetsByStatus(w http.ResponseWriter, r *http.Reque // Deprecated func (c *PetAPIController) FindPetsByTags(w http.ResponseWriter, r *http.Request) { query := r.URL.Query() - tagsParam := strings.Split(query.Get("tags"), ",") + var tagsParam [] string + if query.Has("tags") { + 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 { diff --git a/samples/server/petstore/go-chi-server/go/api_pet_service.go b/samples/server/petstore/go-chi-server/go/api_pet_service.go index bda4cd897526..38f7ba58655d 100644 --- a/samples/server/petstore/go-chi-server/go/api_pet_service.go +++ b/samples/server/petstore/go-chi-server/go/api_pet_service.go @@ -52,6 +52,20 @@ func (s *PetAPIService) DeletePet(ctx context.Context, petId int64, apiKey strin return Response(http.StatusNotImplemented, nil), errors.New("DeletePet method not implemented") } +// FilterPetsByCategory - Finds Pets +func (s *PetAPIService) FilterPetsByCategory(ctx context.Context, gender Gender, species Species, notSpecies []Species) (ImplResponse, error) { + // TODO - update FilterPetsByCategory 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("FilterPetsByCategory 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. diff --git a/samples/server/petstore/go-chi-server/go/model_gender.go b/samples/server/petstore/go-chi-server/go/model_gender.go new file mode 100644 index 000000000000..58b1dcb6ecbc --- /dev/null +++ b/samples/server/petstore/go-chi-server/go/model_gender.go @@ -0,0 +1,64 @@ +/* + * 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 ( + "fmt" +) + + + +type Gender string + +// List of Gender +const ( + MALE Gender = "male" + FEMALE Gender = "female" +) + +// All allowed values of Gender enum +var AllowedGenderEnumValues = []Gender{ + "male", + "female", +} + +// IsValid return true if the value is valid for the enum, false otherwise +func (v Gender) IsValid() bool { + for _, existing := range AllowedGenderEnumValues { + if existing == v { + return true + } + } + return false +} + +// NewGenderFromValue returns a pointer to a valid Gender +// for the value passed as argument, or an error if the value passed is not allowed by the enum +func NewGenderFromValue(v string) (*Gender, error) { + ev := Gender(v) + if ev.IsValid() { + return &ev, nil + } else { + return nil, fmt.Errorf("invalid value '%v' for Gender: valid values are %v", v, AllowedGenderEnumValues) + } +} + + + +// AssertGenderRequired checks if the required fields are not zero-ed +func AssertGenderRequired(obj Gender) error { + return nil +} + +// AssertGenderConstraints checks if the values respects the defined constraints +func AssertGenderConstraints(obj Gender) error { + return nil +} diff --git a/samples/server/petstore/go-chi-server/go/model_species.go b/samples/server/petstore/go-chi-server/go/model_species.go new file mode 100644 index 000000000000..4a3cd280b219 --- /dev/null +++ b/samples/server/petstore/go-chi-server/go/model_species.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 ( + "fmt" +) + + + +type Species string + +// List of Species +const ( + CAT Species = "cat" + DOG Species = "dog" + FISH Species = "fish" + GOAT Species = "goat" + PIG Species = "pig" +) + +// All allowed values of Species enum +var AllowedSpeciesEnumValues = []Species{ + "cat", + "dog", + "fish", + "goat", + "pig", +} + +// IsValid return true if the value is valid for the enum, false otherwise +func (v Species) IsValid() bool { + for _, existing := range AllowedSpeciesEnumValues { + if existing == v { + return true + } + } + return false +} + +// NewSpeciesFromValue returns a pointer to a valid Species +// for the value passed as argument, or an error if the value passed is not allowed by the enum +func NewSpeciesFromValue(v string) (*Species, error) { + ev := Species(v) + if ev.IsValid() { + return &ev, nil + } else { + return nil, fmt.Errorf("invalid value '%v' for Species: valid values are %v", v, AllowedSpeciesEnumValues) + } +} + + + +// AssertSpeciesRequired checks if the required fields are not zero-ed +func AssertSpeciesRequired(obj Species) error { + return nil +} + +// AssertSpeciesConstraints checks if the values respects the defined constraints +func AssertSpeciesConstraints(obj Species) error { + return nil +} From f7dba37cb304449ac011618432265a3b4e0303e1 Mon Sep 17 00:00:00 2001 From: Ian Cubbon Date: Tue, 10 Oct 2023 12:47:16 -0700 Subject: [PATCH 2/9] Fix identation of examples --- samples/openapi3/server/petstore/go/go-petstore/go/api_pet.go | 4 ++-- samples/server/petstore/go-api-server/go/api_pet.go | 4 ++-- samples/server/petstore/go-chi-server/go/api_pet.go | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) 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 index c9f3e6042b39..6a4551307df6 100644 --- a/samples/openapi3/server/petstore/go/go-petstore/go/api_pet.go +++ b/samples/openapi3/server/petstore/go/go-petstore/go/api_pet.go @@ -146,7 +146,7 @@ func (c *PetAPIController) FindPetsByStatus(w http.ResponseWriter, r *http.Reque query := r.URL.Query() var statusParam [] string if query.Has("status") { - statusParam = strings.Split(query.Get("status"), ",") + 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 @@ -164,7 +164,7 @@ func (c *PetAPIController) FindPetsByTags(w http.ResponseWriter, r *http.Request query := r.URL.Query() var tagsParam [] string if query.Has("tags") { - tagsParam = strings.Split(query.Get("tags"), ",") + 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 diff --git a/samples/server/petstore/go-api-server/go/api_pet.go b/samples/server/petstore/go-api-server/go/api_pet.go index fc96fa96047d..5198f1064036 100644 --- a/samples/server/petstore/go-api-server/go/api_pet.go +++ b/samples/server/petstore/go-api-server/go/api_pet.go @@ -189,7 +189,7 @@ func (c *PetAPIController) FindPetsByStatus(w http.ResponseWriter, r *http.Reque query := r.URL.Query() var statusParam [] string if query.Has("status") { - statusParam = strings.Split(query.Get("status"), ",") + 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 @@ -207,7 +207,7 @@ func (c *PetAPIController) FindPetsByTags(w http.ResponseWriter, r *http.Request query := r.URL.Query() var tagsParam [] string if query.Has("tags") { - tagsParam = strings.Split(query.Get("tags"), ",") + 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 diff --git a/samples/server/petstore/go-chi-server/go/api_pet.go b/samples/server/petstore/go-chi-server/go/api_pet.go index 3f6716ee91b6..8895d5344508 100644 --- a/samples/server/petstore/go-chi-server/go/api_pet.go +++ b/samples/server/petstore/go-chi-server/go/api_pet.go @@ -187,7 +187,7 @@ func (c *PetAPIController) FindPetsByStatus(w http.ResponseWriter, r *http.Reque query := r.URL.Query() var statusParam [] string if query.Has("status") { - statusParam = strings.Split(query.Get("status"), ",") + 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 @@ -205,7 +205,7 @@ func (c *PetAPIController) FindPetsByTags(w http.ResponseWriter, r *http.Request query := r.URL.Query() var tagsParam [] string if query.Has("tags") { - tagsParam = strings.Split(query.Get("tags"), ",") + 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 From fa6b244d876f15dd1be719682200b5915fd96875 Mon Sep 17 00:00:00 2001 From: Ian Cubbon Date: Wed, 11 Oct 2023 09:54:12 -0700 Subject: [PATCH 3/9] Pre-allocate the capacity of the slice of Enums to be the correct size. --- .../go-server/controller-api.mustache | 4 +++- .../petstore/go-api-server/go/api_pet.go | 4 +++- .../petstore/go-chi-server/go/api_pet.go | 24 +++++++++---------- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/go-server/controller-api.mustache b/modules/openapi-generator/src/main/resources/go-server/controller-api.mustache index d6936fdb7dc9..7b9508206686 100644 --- a/modules/openapi-generator/src/main/resources/go-server/controller-api.mustache +++ b/modules/openapi-generator/src/main/resources/go-server/controller-api.mustache @@ -348,7 +348,9 @@ func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Re {{#items.isEnumRef}} var {{paramName}}Param []{{items.dataType}} if query.Has("{{baseName}}") { - for _, param := range strings.Split(query.Get("{{baseName}}"), ",") { + paramSplits := strings.Split(query.Get("{{baseName}}"), ",") + {{paramName}}Param = make([]{{items.dataType}}, 0, len(paramSplits)) + for _, param := range paramSplits { paramEnum, err := New{{items.dataType}}FromValue(param) if err != nil { c.errorHandler(w, r, &ParsingError{Err: err}, nil) diff --git a/samples/server/petstore/go-api-server/go/api_pet.go b/samples/server/petstore/go-api-server/go/api_pet.go index 5198f1064036..ea8698f3ab02 100644 --- a/samples/server/petstore/go-api-server/go/api_pet.go +++ b/samples/server/petstore/go-api-server/go/api_pet.go @@ -165,7 +165,9 @@ func (c *PetAPIController) FilterPetsByCategory(w http.ResponseWriter, r *http.R speciesParam := *speciesParamPtr var notSpeciesParam []Species if query.Has("notSpecies") { - for _, param := range strings.Split(query.Get("notSpecies"), ",") { + paramSplits := strings.Split(query.Get("notSpecies"), ",") + notSpeciesParam = make([]Species, 0, len(paramSplits)) + for _, param := range paramSplits { paramEnum, err := NewSpeciesFromValue(param) if err != nil { c.errorHandler(w, r, &ParsingError{Err: err}, nil) diff --git a/samples/server/petstore/go-chi-server/go/api_pet.go b/samples/server/petstore/go-chi-server/go/api_pet.go index 8895d5344508..d3704a38e943 100644 --- a/samples/server/petstore/go-chi-server/go/api_pet.go +++ b/samples/server/petstore/go-chi-server/go/api_pet.go @@ -19,7 +19,7 @@ import ( // PetAPIController binds http requests to an api service and writes the service results to the http response type PetAPIController struct { - service PetAPIServicer + service PetAPIServicer errorHandler ErrorHandler } @@ -163,7 +163,9 @@ func (c *PetAPIController) FilterPetsByCategory(w http.ResponseWriter, r *http.R speciesParam := *speciesParamPtr var notSpeciesParam []Species if query.Has("notSpecies") { - for _, param := range strings.Split(query.Get("notSpecies"), ",") { + paramSplits := strings.Split(query.Get("notSpecies"), ",") + notSpeciesParam = make([]Species, 0, len(paramSplits)) + for _, param := range paramSplits { paramEnum, err := NewSpeciesFromValue(param) if err != nil { c.errorHandler(w, r, &ParsingError{Err: err}, nil) @@ -185,7 +187,7 @@ func (c *PetAPIController) FilterPetsByCategory(w http.ResponseWriter, r *http.R // FindPetsByStatus - Finds Pets by status func (c *PetAPIController) FindPetsByStatus(w http.ResponseWriter, r *http.Request) { query := r.URL.Query() - var statusParam [] string + var statusParam []string if query.Has("status") { statusParam = strings.Split(query.Get("status"), ",") } @@ -203,7 +205,7 @@ func (c *PetAPIController) FindPetsByStatus(w http.ResponseWriter, r *http.Reque // Deprecated func (c *PetAPIController) FindPetsByTags(w http.ResponseWriter, r *http.Request) { query := r.URL.Query() - var tagsParam [] string + var tagsParam []string if query.Has("tags") { tagsParam = strings.Split(query.Get("tags"), ",") } @@ -278,11 +280,9 @@ func (c *PetAPIController) UpdatePetWithForm(w http.ResponseWriter, r *http.Requ 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 @@ -308,17 +308,15 @@ func (c *PetAPIController) UploadFile(w http.ResponseWriter, r *http.Request) { 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 { From 19a370a84022760e8a943fe19407e913611cd445 Mon Sep 17 00:00:00 2001 From: Ian Cubbon Date: Wed, 11 Oct 2023 10:36:04 -0700 Subject: [PATCH 4/9] Formatting and updated examples --- .../resources/go-server/controller-api.mustache | 2 +- .../server/petstore/go/go-petstore/go/api_pet.go | 4 ++-- .../server/petstore/go-api-server/go/api_pet.go | 4 ++-- .../server/petstore/go-chi-server/go/api_pet.go | 16 ++++++++++------ 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/go-server/controller-api.mustache b/modules/openapi-generator/src/main/resources/go-server/controller-api.mustache index 7b9508206686..ed395bf4353e 100644 --- a/modules/openapi-generator/src/main/resources/go-server/controller-api.mustache +++ b/modules/openapi-generator/src/main/resources/go-server/controller-api.mustache @@ -340,7 +340,7 @@ func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Re {{^items.isLong}} {{^items.isInteger}} {{^items.isEnumRef}} - var {{paramName}}Param [] string + var {{paramName}}Param []string if query.Has("{{baseName}}") { {{paramName}}Param = strings.Split(query.Get("{{baseName}}"), ",") } 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 index 6a4551307df6..c3ce38837b14 100644 --- a/samples/openapi3/server/petstore/go/go-petstore/go/api_pet.go +++ b/samples/openapi3/server/petstore/go/go-petstore/go/api_pet.go @@ -144,7 +144,7 @@ func (c *PetAPIController) DeletePet(w http.ResponseWriter, r *http.Request) { // FindPetsByStatus - Finds Pets by status func (c *PetAPIController) FindPetsByStatus(w http.ResponseWriter, r *http.Request) { query := r.URL.Query() - var statusParam [] string + var statusParam []string if query.Has("status") { statusParam = strings.Split(query.Get("status"), ",") } @@ -162,7 +162,7 @@ func (c *PetAPIController) FindPetsByStatus(w http.ResponseWriter, r *http.Reque // Deprecated func (c *PetAPIController) FindPetsByTags(w http.ResponseWriter, r *http.Request) { query := r.URL.Query() - var tagsParam [] string + var tagsParam []string if query.Has("tags") { tagsParam = strings.Split(query.Get("tags"), ",") } diff --git a/samples/server/petstore/go-api-server/go/api_pet.go b/samples/server/petstore/go-api-server/go/api_pet.go index ea8698f3ab02..f0f14c0fcf40 100644 --- a/samples/server/petstore/go-api-server/go/api_pet.go +++ b/samples/server/petstore/go-api-server/go/api_pet.go @@ -189,7 +189,7 @@ func (c *PetAPIController) FilterPetsByCategory(w http.ResponseWriter, r *http.R // FindPetsByStatus - Finds Pets by status func (c *PetAPIController) FindPetsByStatus(w http.ResponseWriter, r *http.Request) { query := r.URL.Query() - var statusParam [] string + var statusParam []string if query.Has("status") { statusParam = strings.Split(query.Get("status"), ",") } @@ -207,7 +207,7 @@ func (c *PetAPIController) FindPetsByStatus(w http.ResponseWriter, r *http.Reque // Deprecated func (c *PetAPIController) FindPetsByTags(w http.ResponseWriter, r *http.Request) { query := r.URL.Query() - var tagsParam [] string + var tagsParam []string if query.Has("tags") { tagsParam = strings.Split(query.Get("tags"), ",") } diff --git a/samples/server/petstore/go-chi-server/go/api_pet.go b/samples/server/petstore/go-chi-server/go/api_pet.go index d3704a38e943..45198c5a851c 100644 --- a/samples/server/petstore/go-chi-server/go/api_pet.go +++ b/samples/server/petstore/go-chi-server/go/api_pet.go @@ -19,7 +19,7 @@ import ( // PetAPIController binds http requests to an api service and writes the service results to the http response type PetAPIController struct { - service PetAPIServicer + service PetAPIServicer errorHandler ErrorHandler } @@ -280,9 +280,11 @@ func (c *PetAPIController) UpdatePetWithForm(w http.ResponseWriter, r *http.Requ 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 @@ -308,15 +310,17 @@ func (c *PetAPIController) UploadFile(w http.ResponseWriter, r *http.Request) { 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 { From 4afc0bed3fd215c62f75af4189da05ca54009f28 Mon Sep 17 00:00:00 2001 From: Ian Cubbon Date: Wed, 11 Oct 2023 12:30:41 -0700 Subject: [PATCH 5/9] Empty-Commit From 7bb5014620ffa533e415f1c0505f86d3a6ab6143 Mon Sep 17 00:00:00 2001 From: Ian Cubbon Date: Thu, 12 Oct 2023 08:56:44 -0700 Subject: [PATCH 6/9] Switch to using a map to store the valid enum values --- .../codegen/languages/GoServerCodegen.java | 4 ++- .../go-server/controller-api.mustache | 13 +++++----- .../main/resources/go-server/model.mustache | 16 +++++------- .../petstore/go-api-server/go/api_pet.go | 10 +++++--- .../petstore/go-api-server/go/model_gender.go | 19 ++++++-------- .../go-api-server/go/model_species.go | 25 ++++++++----------- .../petstore/go-chi-server/go/api_pet.go | 10 +++++--- .../petstore/go-chi-server/go/model_gender.go | 19 ++++++-------- .../go-chi-server/go/model_species.go | 25 ++++++++----------- 9 files changed, 66 insertions(+), 75 deletions(-) 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 fff4b41bb7ab..8ae152283b84 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 @@ -302,13 +302,15 @@ public ModelsMap postProcessModels(ModelsMap objs) { CodegenModel model = m.getModel(); if (model.isEnum) { imports.add(createMapping("import", "fmt")); + imports.add(createMapping("import", "golang.org/x/exp/maps")); continue; } Boolean importErrors = false; for (CodegenProperty param : Iterables.concat(model.vars, model.allVars, model.requiredVars, model.optionalVars)) { - if (param.isNumeric && (StringUtils.isNotEmpty(param.minimum) || StringUtils.isNotEmpty(param.maximum))) { + if (param.isNumeric + && (StringUtils.isNotEmpty(param.minimum) || StringUtils.isNotEmpty(param.maximum))) { importErrors = true; } } diff --git a/modules/openapi-generator/src/main/resources/go-server/controller-api.mustache b/modules/openapi-generator/src/main/resources/go-server/controller-api.mustache index d6936fdb7dc9..76d6c89020c2 100644 --- a/modules/openapi-generator/src/main/resources/go-server/controller-api.mustache +++ b/modules/openapi-generator/src/main/resources/go-server/controller-api.mustache @@ -177,12 +177,11 @@ func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Re {{paramName}}Param := {{#routers}}{{#mux}}params["{{baseName}}"]{{/mux}}{{#chi}}chi.URLParam(r, "{{baseName}}"){{/chi}}{{/routers}} {{/isEnumOrRef}} {{#isEnumOrRef}} - {{paramName}}ParamPtr, err := New{{dataType}}FromValue({{#routers}}{{#mux}}params["{{baseName}}"]{{/mux}}{{#chi}}chi.URLParam(r, "{{baseName}}"){{/chi}}{{/routers}}) + {{paramName}}Param, err := New{{dataType}}FromValue({{#routers}}{{#mux}}params["{{baseName}}"]{{/mux}}{{#chi}}chi.URLParam(r, "{{baseName}}"){{/chi}}{{/routers}}) if err != nil { c.errorHandler(w, r, &ParsingError{Err: err}, nil) return } - {{paramName}}Param := *{{paramName}}ParamPtr {{/isEnumOrRef}} {{/isInteger}} {{/isLong}} @@ -386,12 +385,11 @@ func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Re {{/isEnumOrRef}} {{#isEnumOrRef}} var err error - {{paramName}}ParamPtr, err := New{{dataType}}FromValue(query.Get("{{baseName}}")) + {{paramName}}Param, err = New{{dataType}}FromValue(query.Get("{{baseName}}")) if err != nil { c.errorHandler(w, r, &ParsingError{Err: err}, nil) return } - {{paramName}}Param = *{{paramName}}ParamPtr {{/isEnumOrRef}} } {{/required}} @@ -400,12 +398,15 @@ func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Re {{paramName}}Param := query.Get("{{baseName}}") {{/isEnumOrRef}} {{#isEnumOrRef}} - {{paramName}}ParamPtr, err := New{{dataType}}FromValue(query.Get("{{baseName}}")) + if !query.Has("{{baseName}}"){ + c.errorHandler(w, r, &RequiredError{"{{baseName}}"}, nil) + return + } + {{paramName}}Param, err := New{{dataType}}FromValue(query.Get("{{baseName}}")) if err != nil { c.errorHandler(w, r, &ParsingError{Err: err}, nil) return } - {{paramName}}Param := *{{paramName}}ParamPtr {{/isEnumOrRef}} {{/required}} {{/defaultValue}} 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 f3704a7f08ca..5ad60685bf7f 100644 --- a/modules/openapi-generator/src/main/resources/go-server/model.mustache +++ b/modules/openapi-generator/src/main/resources/go-server/model.mustache @@ -20,32 +20,28 @@ const ( ) // All allowed values of {{{classname}}} enum -var Allowed{{{classname}}}EnumValues = []{{{classname}}}{ +var Allowed{{{classname}}}EnumValues = map[{{{classname}}}][]struct{}{ {{#allowableValues}} {{#enumVars}} - {{{value}}}, + {{{value}}}: {}, {{/enumVars}} {{/allowableValues}} } // IsValid return true if the value is valid for the enum, false otherwise func (v {{{classname}}}) IsValid() bool { - for _, existing := range Allowed{{{classname}}}EnumValues { - if existing == v { - return true - } - } - return false + _, ok := Allowed{{{classname}}}EnumValues[v] + return ok } // New{{{classname}}}FromValue returns a pointer to a valid {{{classname}}} // for the value passed as argument, or an error if the value passed is not allowed by the enum -func New{{{classname}}}FromValue(v {{{format}}}{{^format}}{{dataType}}{{/format}}) (*{{{classname}}}, error) { +func New{{{classname}}}FromValue(v {{{format}}}{{^format}}{{dataType}}{{/format}}) ({{{classname}}}, error) { ev := {{{classname}}}(v) if ev.IsValid() { return &ev, nil } else { - return nil, fmt.Errorf("invalid value '%v' for {{{classname}}}: valid values are %v", v, Allowed{{{classname}}}EnumValues) + return nil, fmt.Errorf("invalid value '%v' for {{{classname}}}: valid values are %v", v, maps.Keys(Allowed{{{classname}}}EnumValues)) } } diff --git a/samples/server/petstore/go-api-server/go/api_pet.go b/samples/server/petstore/go-api-server/go/api_pet.go index 5198f1064036..8be00cbcb438 100644 --- a/samples/server/petstore/go-api-server/go/api_pet.go +++ b/samples/server/petstore/go-api-server/go/api_pet.go @@ -151,18 +151,20 @@ func (c *PetAPIController) DeletePet(w http.ResponseWriter, r *http.Request) { func (c *PetAPIController) FilterPetsByCategory(w http.ResponseWriter, r *http.Request) { params := mux.Vars(r) query := r.URL.Query() - genderParamPtr, err := NewGenderFromValue(params["gender"]) + genderParam, err := NewGenderFromValue(params["gender"]) if err != nil { c.errorHandler(w, r, &ParsingError{Err: err}, nil) return } - genderParam := *genderParamPtr - speciesParamPtr, err := NewSpeciesFromValue(query.Get("species")) + if !query.Has("species"){ + c.errorHandler(w, r, &RequiredError{"species"}, nil) + return + } + speciesParam, err := NewSpeciesFromValue(query.Get("species")) if err != nil { c.errorHandler(w, r, &ParsingError{Err: err}, nil) return } - speciesParam := *speciesParamPtr var notSpeciesParam []Species if query.Has("notSpecies") { for _, param := range strings.Split(query.Get("notSpecies"), ",") { diff --git a/samples/server/petstore/go-api-server/go/model_gender.go b/samples/server/petstore/go-api-server/go/model_gender.go index 58b1dcb6ecbc..2f6aa3ff6382 100644 --- a/samples/server/petstore/go-api-server/go/model_gender.go +++ b/samples/server/petstore/go-api-server/go/model_gender.go @@ -12,6 +12,7 @@ package petstoreserver import ( "fmt" + "golang.org/x/exp/maps" ) @@ -25,29 +26,25 @@ const ( ) // All allowed values of Gender enum -var AllowedGenderEnumValues = []Gender{ - "male", - "female", +var AllowedGenderEnumValues = map[Gender][]struct{}{ + "male": {}, + "female": {}, } // IsValid return true if the value is valid for the enum, false otherwise func (v Gender) IsValid() bool { - for _, existing := range AllowedGenderEnumValues { - if existing == v { - return true - } - } - return false + _, ok := AllowedGenderEnumValues[v] + return ok } // NewGenderFromValue returns a pointer to a valid Gender // for the value passed as argument, or an error if the value passed is not allowed by the enum -func NewGenderFromValue(v string) (*Gender, error) { +func NewGenderFromValue(v string) (Gender, error) { ev := Gender(v) if ev.IsValid() { return &ev, nil } else { - return nil, fmt.Errorf("invalid value '%v' for Gender: valid values are %v", v, AllowedGenderEnumValues) + return nil, fmt.Errorf("invalid value '%v' for Gender: valid values are %v", v, maps.Keys(AllowedGenderEnumValues)) } } diff --git a/samples/server/petstore/go-api-server/go/model_species.go b/samples/server/petstore/go-api-server/go/model_species.go index 4a3cd280b219..70e6ec1bedbd 100644 --- a/samples/server/petstore/go-api-server/go/model_species.go +++ b/samples/server/petstore/go-api-server/go/model_species.go @@ -12,6 +12,7 @@ package petstoreserver import ( "fmt" + "golang.org/x/exp/maps" ) @@ -28,32 +29,28 @@ const ( ) // All allowed values of Species enum -var AllowedSpeciesEnumValues = []Species{ - "cat", - "dog", - "fish", - "goat", - "pig", +var AllowedSpeciesEnumValues = map[Species][]struct{}{ + "cat": {}, + "dog": {}, + "fish": {}, + "goat": {}, + "pig": {}, } // IsValid return true if the value is valid for the enum, false otherwise func (v Species) IsValid() bool { - for _, existing := range AllowedSpeciesEnumValues { - if existing == v { - return true - } - } - return false + _, ok := AllowedSpeciesEnumValues[v] + return ok } // NewSpeciesFromValue returns a pointer to a valid Species // for the value passed as argument, or an error if the value passed is not allowed by the enum -func NewSpeciesFromValue(v string) (*Species, error) { +func NewSpeciesFromValue(v string) (Species, error) { ev := Species(v) if ev.IsValid() { return &ev, nil } else { - return nil, fmt.Errorf("invalid value '%v' for Species: valid values are %v", v, AllowedSpeciesEnumValues) + return nil, fmt.Errorf("invalid value '%v' for Species: valid values are %v", v, maps.Keys(AllowedSpeciesEnumValues)) } } diff --git a/samples/server/petstore/go-chi-server/go/api_pet.go b/samples/server/petstore/go-chi-server/go/api_pet.go index 8895d5344508..cb8271d08663 100644 --- a/samples/server/petstore/go-chi-server/go/api_pet.go +++ b/samples/server/petstore/go-chi-server/go/api_pet.go @@ -149,18 +149,20 @@ func (c *PetAPIController) DeletePet(w http.ResponseWriter, r *http.Request) { // FilterPetsByCategory - Finds Pets func (c *PetAPIController) FilterPetsByCategory(w http.ResponseWriter, r *http.Request) { query := r.URL.Query() - genderParamPtr, err := NewGenderFromValue(chi.URLParam(r, "gender")) + genderParam, err := NewGenderFromValue(chi.URLParam(r, "gender")) if err != nil { c.errorHandler(w, r, &ParsingError{Err: err}, nil) return } - genderParam := *genderParamPtr - speciesParamPtr, err := NewSpeciesFromValue(query.Get("species")) + if !query.Has("species"){ + c.errorHandler(w, r, &RequiredError{"species"}, nil) + return + } + speciesParam, err := NewSpeciesFromValue(query.Get("species")) if err != nil { c.errorHandler(w, r, &ParsingError{Err: err}, nil) return } - speciesParam := *speciesParamPtr var notSpeciesParam []Species if query.Has("notSpecies") { for _, param := range strings.Split(query.Get("notSpecies"), ",") { diff --git a/samples/server/petstore/go-chi-server/go/model_gender.go b/samples/server/petstore/go-chi-server/go/model_gender.go index 58b1dcb6ecbc..2f6aa3ff6382 100644 --- a/samples/server/petstore/go-chi-server/go/model_gender.go +++ b/samples/server/petstore/go-chi-server/go/model_gender.go @@ -12,6 +12,7 @@ package petstoreserver import ( "fmt" + "golang.org/x/exp/maps" ) @@ -25,29 +26,25 @@ const ( ) // All allowed values of Gender enum -var AllowedGenderEnumValues = []Gender{ - "male", - "female", +var AllowedGenderEnumValues = map[Gender][]struct{}{ + "male": {}, + "female": {}, } // IsValid return true if the value is valid for the enum, false otherwise func (v Gender) IsValid() bool { - for _, existing := range AllowedGenderEnumValues { - if existing == v { - return true - } - } - return false + _, ok := AllowedGenderEnumValues[v] + return ok } // NewGenderFromValue returns a pointer to a valid Gender // for the value passed as argument, or an error if the value passed is not allowed by the enum -func NewGenderFromValue(v string) (*Gender, error) { +func NewGenderFromValue(v string) (Gender, error) { ev := Gender(v) if ev.IsValid() { return &ev, nil } else { - return nil, fmt.Errorf("invalid value '%v' for Gender: valid values are %v", v, AllowedGenderEnumValues) + return nil, fmt.Errorf("invalid value '%v' for Gender: valid values are %v", v, maps.Keys(AllowedGenderEnumValues)) } } diff --git a/samples/server/petstore/go-chi-server/go/model_species.go b/samples/server/petstore/go-chi-server/go/model_species.go index 4a3cd280b219..70e6ec1bedbd 100644 --- a/samples/server/petstore/go-chi-server/go/model_species.go +++ b/samples/server/petstore/go-chi-server/go/model_species.go @@ -12,6 +12,7 @@ package petstoreserver import ( "fmt" + "golang.org/x/exp/maps" ) @@ -28,32 +29,28 @@ const ( ) // All allowed values of Species enum -var AllowedSpeciesEnumValues = []Species{ - "cat", - "dog", - "fish", - "goat", - "pig", +var AllowedSpeciesEnumValues = map[Species][]struct{}{ + "cat": {}, + "dog": {}, + "fish": {}, + "goat": {}, + "pig": {}, } // IsValid return true if the value is valid for the enum, false otherwise func (v Species) IsValid() bool { - for _, existing := range AllowedSpeciesEnumValues { - if existing == v { - return true - } - } - return false + _, ok := AllowedSpeciesEnumValues[v] + return ok } // NewSpeciesFromValue returns a pointer to a valid Species // for the value passed as argument, or an error if the value passed is not allowed by the enum -func NewSpeciesFromValue(v string) (*Species, error) { +func NewSpeciesFromValue(v string) (Species, error) { ev := Species(v) if ev.IsValid() { return &ev, nil } else { - return nil, fmt.Errorf("invalid value '%v' for Species: valid values are %v", v, AllowedSpeciesEnumValues) + return nil, fmt.Errorf("invalid value '%v' for Species: valid values are %v", v, maps.Keys(AllowedSpeciesEnumValues)) } } From 5a616b00b312e6c717aeb30b467f1c4297d8abc8 Mon Sep 17 00:00:00 2001 From: Ian Cubbon Date: Thu, 12 Oct 2023 09:25:39 -0700 Subject: [PATCH 7/9] Fixed pointer derefs missed from previous change in PR --- .../src/main/resources/go-server/controller-api.mustache | 2 +- .../src/main/resources/go-server/model.mustache | 2 +- samples/server/petstore/go-api-server/go/api_pet.go | 2 +- samples/server/petstore/go-api-server/go/model_gender.go | 2 +- samples/server/petstore/go-api-server/go/model_species.go | 2 +- samples/server/petstore/go-chi-server/go/api_pet.go | 2 +- samples/server/petstore/go-chi-server/go/model_gender.go | 2 +- samples/server/petstore/go-chi-server/go/model_species.go | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/go-server/controller-api.mustache b/modules/openapi-generator/src/main/resources/go-server/controller-api.mustache index 86543f34af9e..d9ccad45e85a 100644 --- a/modules/openapi-generator/src/main/resources/go-server/controller-api.mustache +++ b/modules/openapi-generator/src/main/resources/go-server/controller-api.mustache @@ -355,7 +355,7 @@ func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Re c.errorHandler(w, r, &ParsingError{Err: err}, nil) return } - {{paramName}}Param = append({{paramName}}Param, *paramEnum) + {{paramName}}Param = append({{paramName}}Param, paramEnum) } } {{/items.isEnumRef}} 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 5ad60685bf7f..aec505897d1e 100644 --- a/modules/openapi-generator/src/main/resources/go-server/model.mustache +++ b/modules/openapi-generator/src/main/resources/go-server/model.mustache @@ -39,7 +39,7 @@ func (v {{{classname}}}) IsValid() bool { func New{{{classname}}}FromValue(v {{{format}}}{{^format}}{{dataType}}{{/format}}) ({{{classname}}}, error) { ev := {{{classname}}}(v) if ev.IsValid() { - return &ev, nil + return ev, nil } else { return nil, fmt.Errorf("invalid value '%v' for {{{classname}}}: valid values are %v", v, maps.Keys(Allowed{{{classname}}}EnumValues)) } diff --git a/samples/server/petstore/go-api-server/go/api_pet.go b/samples/server/petstore/go-api-server/go/api_pet.go index 356e2f37ef54..a02368dafccf 100644 --- a/samples/server/petstore/go-api-server/go/api_pet.go +++ b/samples/server/petstore/go-api-server/go/api_pet.go @@ -175,7 +175,7 @@ func (c *PetAPIController) FilterPetsByCategory(w http.ResponseWriter, r *http.R c.errorHandler(w, r, &ParsingError{Err: err}, nil) return } - notSpeciesParam = append(notSpeciesParam, *paramEnum) + notSpeciesParam = append(notSpeciesParam, paramEnum) } } result, err := c.service.FilterPetsByCategory(r.Context(), genderParam, speciesParam, notSpeciesParam) diff --git a/samples/server/petstore/go-api-server/go/model_gender.go b/samples/server/petstore/go-api-server/go/model_gender.go index 2f6aa3ff6382..f6581802a863 100644 --- a/samples/server/petstore/go-api-server/go/model_gender.go +++ b/samples/server/petstore/go-api-server/go/model_gender.go @@ -42,7 +42,7 @@ func (v Gender) IsValid() bool { func NewGenderFromValue(v string) (Gender, error) { ev := Gender(v) if ev.IsValid() { - return &ev, nil + return ev, nil } else { return nil, fmt.Errorf("invalid value '%v' for Gender: valid values are %v", v, maps.Keys(AllowedGenderEnumValues)) } diff --git a/samples/server/petstore/go-api-server/go/model_species.go b/samples/server/petstore/go-api-server/go/model_species.go index 70e6ec1bedbd..7cd1e8d0eaa3 100644 --- a/samples/server/petstore/go-api-server/go/model_species.go +++ b/samples/server/petstore/go-api-server/go/model_species.go @@ -48,7 +48,7 @@ func (v Species) IsValid() bool { func NewSpeciesFromValue(v string) (Species, error) { ev := Species(v) if ev.IsValid() { - return &ev, nil + return ev, nil } else { return nil, fmt.Errorf("invalid value '%v' for Species: valid values are %v", v, maps.Keys(AllowedSpeciesEnumValues)) } diff --git a/samples/server/petstore/go-chi-server/go/api_pet.go b/samples/server/petstore/go-chi-server/go/api_pet.go index bb18b994dca1..75bb83522c73 100644 --- a/samples/server/petstore/go-chi-server/go/api_pet.go +++ b/samples/server/petstore/go-chi-server/go/api_pet.go @@ -173,7 +173,7 @@ func (c *PetAPIController) FilterPetsByCategory(w http.ResponseWriter, r *http.R c.errorHandler(w, r, &ParsingError{Err: err}, nil) return } - notSpeciesParam = append(notSpeciesParam, *paramEnum) + notSpeciesParam = append(notSpeciesParam, paramEnum) } } result, err := c.service.FilterPetsByCategory(r.Context(), genderParam, speciesParam, notSpeciesParam) diff --git a/samples/server/petstore/go-chi-server/go/model_gender.go b/samples/server/petstore/go-chi-server/go/model_gender.go index 2f6aa3ff6382..f6581802a863 100644 --- a/samples/server/petstore/go-chi-server/go/model_gender.go +++ b/samples/server/petstore/go-chi-server/go/model_gender.go @@ -42,7 +42,7 @@ func (v Gender) IsValid() bool { func NewGenderFromValue(v string) (Gender, error) { ev := Gender(v) if ev.IsValid() { - return &ev, nil + return ev, nil } else { return nil, fmt.Errorf("invalid value '%v' for Gender: valid values are %v", v, maps.Keys(AllowedGenderEnumValues)) } diff --git a/samples/server/petstore/go-chi-server/go/model_species.go b/samples/server/petstore/go-chi-server/go/model_species.go index 70e6ec1bedbd..7cd1e8d0eaa3 100644 --- a/samples/server/petstore/go-chi-server/go/model_species.go +++ b/samples/server/petstore/go-chi-server/go/model_species.go @@ -48,7 +48,7 @@ func (v Species) IsValid() bool { func NewSpeciesFromValue(v string) (Species, error) { ev := Species(v) if ev.IsValid() { - return &ev, nil + return ev, nil } else { return nil, fmt.Errorf("invalid value '%v' for Species: valid values are %v", v, maps.Keys(AllowedSpeciesEnumValues)) } From 9c23dc4bc35c6eae91dc9d37c477c215dbb14fd3 Mon Sep 17 00:00:00 2001 From: Ian Cubbon Date: Thu, 12 Oct 2023 09:36:28 -0700 Subject: [PATCH 8/9] More fixing of pointer to not pointer --- .../src/main/resources/go-server/model.mustache | 2 +- samples/server/petstore/go-api-server/go/model_gender.go | 2 +- samples/server/petstore/go-api-server/go/model_species.go | 2 +- samples/server/petstore/go-chi-server/go/model_gender.go | 2 +- samples/server/petstore/go-chi-server/go/model_species.go | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) 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 aec505897d1e..a567549bafaf 100644 --- a/modules/openapi-generator/src/main/resources/go-server/model.mustache +++ b/modules/openapi-generator/src/main/resources/go-server/model.mustache @@ -41,7 +41,7 @@ func New{{{classname}}}FromValue(v {{{format}}}{{^format}}{{dataType}}{{/format} if ev.IsValid() { return ev, nil } else { - return nil, fmt.Errorf("invalid value '%v' for {{{classname}}}: valid values are %v", v, maps.Keys(Allowed{{{classname}}}EnumValues)) + return "", fmt.Errorf("invalid value '%v' for {{{classname}}}: valid values are %v", v, maps.Keys(Allowed{{{classname}}}EnumValues)) } } diff --git a/samples/server/petstore/go-api-server/go/model_gender.go b/samples/server/petstore/go-api-server/go/model_gender.go index f6581802a863..7e95e9f2128b 100644 --- a/samples/server/petstore/go-api-server/go/model_gender.go +++ b/samples/server/petstore/go-api-server/go/model_gender.go @@ -44,7 +44,7 @@ func NewGenderFromValue(v string) (Gender, error) { if ev.IsValid() { return ev, nil } else { - return nil, fmt.Errorf("invalid value '%v' for Gender: valid values are %v", v, maps.Keys(AllowedGenderEnumValues)) + return "", fmt.Errorf("invalid value '%v' for Gender: valid values are %v", v, maps.Keys(AllowedGenderEnumValues)) } } diff --git a/samples/server/petstore/go-api-server/go/model_species.go b/samples/server/petstore/go-api-server/go/model_species.go index 7cd1e8d0eaa3..0e241f64e455 100644 --- a/samples/server/petstore/go-api-server/go/model_species.go +++ b/samples/server/petstore/go-api-server/go/model_species.go @@ -50,7 +50,7 @@ func NewSpeciesFromValue(v string) (Species, error) { if ev.IsValid() { return ev, nil } else { - return nil, fmt.Errorf("invalid value '%v' for Species: valid values are %v", v, maps.Keys(AllowedSpeciesEnumValues)) + return "", fmt.Errorf("invalid value '%v' for Species: valid values are %v", v, maps.Keys(AllowedSpeciesEnumValues)) } } diff --git a/samples/server/petstore/go-chi-server/go/model_gender.go b/samples/server/petstore/go-chi-server/go/model_gender.go index f6581802a863..7e95e9f2128b 100644 --- a/samples/server/petstore/go-chi-server/go/model_gender.go +++ b/samples/server/petstore/go-chi-server/go/model_gender.go @@ -44,7 +44,7 @@ func NewGenderFromValue(v string) (Gender, error) { if ev.IsValid() { return ev, nil } else { - return nil, fmt.Errorf("invalid value '%v' for Gender: valid values are %v", v, maps.Keys(AllowedGenderEnumValues)) + return "", fmt.Errorf("invalid value '%v' for Gender: valid values are %v", v, maps.Keys(AllowedGenderEnumValues)) } } diff --git a/samples/server/petstore/go-chi-server/go/model_species.go b/samples/server/petstore/go-chi-server/go/model_species.go index 7cd1e8d0eaa3..0e241f64e455 100644 --- a/samples/server/petstore/go-chi-server/go/model_species.go +++ b/samples/server/petstore/go-chi-server/go/model_species.go @@ -50,7 +50,7 @@ func NewSpeciesFromValue(v string) (Species, error) { if ev.IsValid() { return ev, nil } else { - return nil, fmt.Errorf("invalid value '%v' for Species: valid values are %v", v, maps.Keys(AllowedSpeciesEnumValues)) + return "", fmt.Errorf("invalid value '%v' for Species: valid values are %v", v, maps.Keys(AllowedSpeciesEnumValues)) } } From fb1652cf0f15256c76589c80c7f6767a70f0ecd6 Mon Sep 17 00:00:00 2001 From: Ian Cubbon Date: Mon, 16 Oct 2023 09:21:23 -0700 Subject: [PATCH 9/9] Create a map for validation and a list of enums for messaging --- .../codegen/languages/GoServerCodegen.java | 4 +--- .../go-server/controller-api.mustache | 6 +++--- .../main/resources/go-server/model.mustache | 17 +++++++++++++---- .../petstore/go-api-server/go/model_gender.go | 15 ++++++++++----- .../petstore/go-api-server/go/model_species.go | 18 +++++++++++++----- .../petstore/go-chi-server/go/model_gender.go | 15 ++++++++++----- .../petstore/go-chi-server/go/model_species.go | 18 +++++++++++++----- 7 files changed, 63 insertions(+), 30 deletions(-) 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 8ae152283b84..fff4b41bb7ab 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 @@ -302,15 +302,13 @@ public ModelsMap postProcessModels(ModelsMap objs) { CodegenModel model = m.getModel(); if (model.isEnum) { imports.add(createMapping("import", "fmt")); - imports.add(createMapping("import", "golang.org/x/exp/maps")); continue; } Boolean importErrors = false; for (CodegenProperty param : Iterables.concat(model.vars, model.allVars, model.requiredVars, model.optionalVars)) { - if (param.isNumeric - && (StringUtils.isNotEmpty(param.minimum) || StringUtils.isNotEmpty(param.maximum))) { + if (param.isNumeric && (StringUtils.isNotEmpty(param.minimum) || StringUtils.isNotEmpty(param.maximum))) { importErrors = true; } } diff --git a/modules/openapi-generator/src/main/resources/go-server/controller-api.mustache b/modules/openapi-generator/src/main/resources/go-server/controller-api.mustache index d9ccad45e85a..265dcd46a22b 100644 --- a/modules/openapi-generator/src/main/resources/go-server/controller-api.mustache +++ b/modules/openapi-generator/src/main/resources/go-server/controller-api.mustache @@ -373,8 +373,9 @@ func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Re {{^isBoolean}} {{^isArray}} {{#defaultValue}} + {{paramName}}Param := "{{defaultValue}}" if query.Has("{{baseName}}") { - {{paramName}}Param := {{^isString}}{{dataType}}( {{/isString}}query.Get("{{baseName}}"){{^isString}} ){{/isString}} + {{paramName}}Param = {{^isString}}{{dataType}}( {{/isString}}query.Get("{{baseName}}"){{^isString}} ){{/isString}} } {{/defaultValue}} {{^defaultValue}} @@ -382,8 +383,7 @@ func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Re var {{paramName}}Param {{dataType}} if query.Has("{{baseName}}") { {{^isEnumOrRef}} - param := query.Get("{{baseName}}") - {{paramName}}Param = ¶m + {{paramName}}Param = query.Get("{{baseName}}") {{/isEnumOrRef}} {{#isEnumOrRef}} var err error 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 a567549bafaf..ce00067fc0b5 100644 --- a/modules/openapi-generator/src/main/resources/go-server/model.mustache +++ b/modules/openapi-generator/src/main/resources/go-server/model.mustache @@ -19,8 +19,17 @@ const ( {{/allowableValues}} ) -// All allowed values of {{{classname}}} enum -var Allowed{{{classname}}}EnumValues = map[{{{classname}}}][]struct{}{ +// Allowed{{{classname}}}EnumValues is all the allowed values of {{{classname}}} enum +var Allowed{{{classname}}}EnumValues = []{{{classname}}}{ + {{#allowableValues}} + {{#enumVars}} + {{{value}}}, + {{/enumVars}} + {{/allowableValues}} +} + +// valid{{{classname}}}EnumValue provides a map of {{classname}}s for fast verification of use input +var valid{{{classname}}}EnumValues = map[{{{classname}}}]struct{}{ {{#allowableValues}} {{#enumVars}} {{{value}}}: {}, @@ -30,7 +39,7 @@ var Allowed{{{classname}}}EnumValues = map[{{{classname}}}][]struct{}{ // IsValid return true if the value is valid for the enum, false otherwise func (v {{{classname}}}) IsValid() bool { - _, ok := Allowed{{{classname}}}EnumValues[v] + _, ok := valid{{{classname}}}EnumValues[v] return ok } @@ -41,7 +50,7 @@ func New{{{classname}}}FromValue(v {{{format}}}{{^format}}{{dataType}}{{/format} if ev.IsValid() { return ev, nil } else { - return "", fmt.Errorf("invalid value '%v' for {{{classname}}}: valid values are %v", v, maps.Keys(Allowed{{{classname}}}EnumValues)) + return "", fmt.Errorf("invalid value '%v' for {{{classname}}}: valid values are %v", v, Allowed{{{classname}}}EnumValues) } } diff --git a/samples/server/petstore/go-api-server/go/model_gender.go b/samples/server/petstore/go-api-server/go/model_gender.go index 7e95e9f2128b..16583a0c400b 100644 --- a/samples/server/petstore/go-api-server/go/model_gender.go +++ b/samples/server/petstore/go-api-server/go/model_gender.go @@ -12,7 +12,6 @@ package petstoreserver import ( "fmt" - "golang.org/x/exp/maps" ) @@ -25,15 +24,21 @@ const ( FEMALE Gender = "female" ) -// All allowed values of Gender enum -var AllowedGenderEnumValues = map[Gender][]struct{}{ +// AllowedGenderEnumValues is all the allowed values of Gender enum +var AllowedGenderEnumValues = []Gender{ + "male", + "female", +} + +// validGenderEnumValue provides a map of Genders for fast verification of use input +var validGenderEnumValues = map[Gender]struct{}{ "male": {}, "female": {}, } // IsValid return true if the value is valid for the enum, false otherwise func (v Gender) IsValid() bool { - _, ok := AllowedGenderEnumValues[v] + _, ok := validGenderEnumValues[v] return ok } @@ -44,7 +49,7 @@ func NewGenderFromValue(v string) (Gender, error) { if ev.IsValid() { return ev, nil } else { - return "", fmt.Errorf("invalid value '%v' for Gender: valid values are %v", v, maps.Keys(AllowedGenderEnumValues)) + return "", fmt.Errorf("invalid value '%v' for Gender: valid values are %v", v, AllowedGenderEnumValues) } } diff --git a/samples/server/petstore/go-api-server/go/model_species.go b/samples/server/petstore/go-api-server/go/model_species.go index 0e241f64e455..4e6fc567e6a4 100644 --- a/samples/server/petstore/go-api-server/go/model_species.go +++ b/samples/server/petstore/go-api-server/go/model_species.go @@ -12,7 +12,6 @@ package petstoreserver import ( "fmt" - "golang.org/x/exp/maps" ) @@ -28,8 +27,17 @@ const ( PIG Species = "pig" ) -// All allowed values of Species enum -var AllowedSpeciesEnumValues = map[Species][]struct{}{ +// AllowedSpeciesEnumValues is all the allowed values of Species enum +var AllowedSpeciesEnumValues = []Species{ + "cat", + "dog", + "fish", + "goat", + "pig", +} + +// validSpeciesEnumValue provides a map of Speciess for fast verification of use input +var validSpeciesEnumValues = map[Species]struct{}{ "cat": {}, "dog": {}, "fish": {}, @@ -39,7 +47,7 @@ var AllowedSpeciesEnumValues = map[Species][]struct{}{ // IsValid return true if the value is valid for the enum, false otherwise func (v Species) IsValid() bool { - _, ok := AllowedSpeciesEnumValues[v] + _, ok := validSpeciesEnumValues[v] return ok } @@ -50,7 +58,7 @@ func NewSpeciesFromValue(v string) (Species, error) { if ev.IsValid() { return ev, nil } else { - return "", fmt.Errorf("invalid value '%v' for Species: valid values are %v", v, maps.Keys(AllowedSpeciesEnumValues)) + return "", fmt.Errorf("invalid value '%v' for Species: valid values are %v", v, AllowedSpeciesEnumValues) } } diff --git a/samples/server/petstore/go-chi-server/go/model_gender.go b/samples/server/petstore/go-chi-server/go/model_gender.go index 7e95e9f2128b..16583a0c400b 100644 --- a/samples/server/petstore/go-chi-server/go/model_gender.go +++ b/samples/server/petstore/go-chi-server/go/model_gender.go @@ -12,7 +12,6 @@ package petstoreserver import ( "fmt" - "golang.org/x/exp/maps" ) @@ -25,15 +24,21 @@ const ( FEMALE Gender = "female" ) -// All allowed values of Gender enum -var AllowedGenderEnumValues = map[Gender][]struct{}{ +// AllowedGenderEnumValues is all the allowed values of Gender enum +var AllowedGenderEnumValues = []Gender{ + "male", + "female", +} + +// validGenderEnumValue provides a map of Genders for fast verification of use input +var validGenderEnumValues = map[Gender]struct{}{ "male": {}, "female": {}, } // IsValid return true if the value is valid for the enum, false otherwise func (v Gender) IsValid() bool { - _, ok := AllowedGenderEnumValues[v] + _, ok := validGenderEnumValues[v] return ok } @@ -44,7 +49,7 @@ func NewGenderFromValue(v string) (Gender, error) { if ev.IsValid() { return ev, nil } else { - return "", fmt.Errorf("invalid value '%v' for Gender: valid values are %v", v, maps.Keys(AllowedGenderEnumValues)) + return "", fmt.Errorf("invalid value '%v' for Gender: valid values are %v", v, AllowedGenderEnumValues) } } diff --git a/samples/server/petstore/go-chi-server/go/model_species.go b/samples/server/petstore/go-chi-server/go/model_species.go index 0e241f64e455..4e6fc567e6a4 100644 --- a/samples/server/petstore/go-chi-server/go/model_species.go +++ b/samples/server/petstore/go-chi-server/go/model_species.go @@ -12,7 +12,6 @@ package petstoreserver import ( "fmt" - "golang.org/x/exp/maps" ) @@ -28,8 +27,17 @@ const ( PIG Species = "pig" ) -// All allowed values of Species enum -var AllowedSpeciesEnumValues = map[Species][]struct{}{ +// AllowedSpeciesEnumValues is all the allowed values of Species enum +var AllowedSpeciesEnumValues = []Species{ + "cat", + "dog", + "fish", + "goat", + "pig", +} + +// validSpeciesEnumValue provides a map of Speciess for fast verification of use input +var validSpeciesEnumValues = map[Species]struct{}{ "cat": {}, "dog": {}, "fish": {}, @@ -39,7 +47,7 @@ var AllowedSpeciesEnumValues = map[Species][]struct{}{ // IsValid return true if the value is valid for the enum, false otherwise func (v Species) IsValid() bool { - _, ok := AllowedSpeciesEnumValues[v] + _, ok := validSpeciesEnumValues[v] return ok } @@ -50,7 +58,7 @@ func NewSpeciesFromValue(v string) (Species, error) { if ev.IsValid() { return ev, nil } else { - return "", fmt.Errorf("invalid value '%v' for Species: valid values are %v", v, maps.Keys(AllowedSpeciesEnumValues)) + return "", fmt.Errorf("invalid value '%v' for Species: valid values are %v", v, AllowedSpeciesEnumValues) } }