[Go-server] - Support for Enums in the Path and Query (#16781)

* 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.

* Fix identation of examples

* Pre-allocate the capacity of the slice of Enums to be
the correct size.

* Formatting and updated examples

* Empty-Commit

* Switch to using a map to store the valid enum values

* Fixed pointer derefs missed from previous change in PR

* More fixing of pointer to not pointer

* Create a map for validation and a list of enums for messaging
This commit is contained in:
Ian Cubbon 2023-10-16 20:35:39 -07:00 committed by GitHub
parent d1fa38e286
commit 1dd9590064
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 718 additions and 9 deletions

View File

@ -301,6 +301,7 @@ public class GoServerCodegen extends AbstractGoCodegen {
CodegenModel model = m.getModel(); CodegenModel model = m.getModel();
if (model.isEnum) { if (model.isEnum) {
imports.add(createMapping("import", "fmt"));
continue; continue;
} }

View File

@ -173,7 +173,16 @@ func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Re
{{^isDouble}} {{^isDouble}}
{{^isLong}} {{^isLong}}
{{^isInteger}} {{^isInteger}}
{{^isEnumOrRef}}
{{paramName}}Param := {{#routers}}{{#mux}}params["{{baseName}}"]{{/mux}}{{#chi}}chi.URLParam(r, "{{baseName}}"){{/chi}}{{/routers}} {{paramName}}Param := {{#routers}}{{#mux}}params["{{baseName}}"]{{/mux}}{{#chi}}chi.URLParam(r, "{{baseName}}"){{/chi}}{{/routers}}
{{/isEnumOrRef}}
{{#isEnumOrRef}}
{{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
}
{{/isEnumOrRef}}
{{/isInteger}} {{/isInteger}}
{{/isLong}} {{/isLong}}
{{/isDouble}} {{/isDouble}}
@ -329,7 +338,27 @@ func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Re
{{^items.isDouble}} {{^items.isDouble}}
{{^items.isLong}} {{^items.isLong}}
{{^items.isInteger}} {{^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}}") {
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)
return
}
{{paramName}}Param = append({{paramName}}Param, paramEnum)
}
}
{{/items.isEnumRef}}
{{/items.isInteger}} {{/items.isInteger}}
{{/items.isLong}} {{/items.isLong}}
{{/items.isDouble}} {{/items.isDouble}}
@ -346,11 +375,42 @@ func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Re
{{#defaultValue}} {{#defaultValue}}
{{paramName}}Param := "{{defaultValue}}" {{paramName}}Param := "{{defaultValue}}"
if query.Has("{{baseName}}") { if query.Has("{{baseName}}") {
{{paramName}}Param = query.Get("{{baseName}}") {{paramName}}Param = {{^isString}}{{dataType}}( {{/isString}}query.Get("{{baseName}}"){{^isString}} ){{/isString}}
} }
{{/defaultValue}} {{/defaultValue}}
{{^defaultValue}} {{^defaultValue}}
{{^required}}
var {{paramName}}Param {{dataType}}
if query.Has("{{baseName}}") {
{{^isEnumOrRef}}
{{paramName}}Param = query.Get("{{baseName}}")
{{/isEnumOrRef}}
{{#isEnumOrRef}}
var err error
{{paramName}}Param, err = New{{dataType}}FromValue(query.Get("{{baseName}}"))
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}
{{/isEnumOrRef}}
}
{{/required}}
{{#required}}
{{^isEnumOrRef}}
{{paramName}}Param := query.Get("{{baseName}}") {{paramName}}Param := query.Get("{{baseName}}")
{{/isEnumOrRef}}
{{#isEnumOrRef}}
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
}
{{/isEnumOrRef}}
{{/required}}
{{/defaultValue}} {{/defaultValue}}
{{/isArray}} {{/isArray}}
{{/isBoolean}} {{/isBoolean}}

View File

@ -17,7 +17,44 @@ const (
{{#enumClassPrefix}}{{{classname.toUpperCase}}}_{{/enumClassPrefix}}{{name}} {{{classname}}} = {{{value}}} {{#enumClassPrefix}}{{{classname.toUpperCase}}}_{{/enumClassPrefix}}{{name}} {{{classname}}} = {{{value}}}
{{/enumVars}} {{/enumVars}}
{{/allowableValues}} {{/allowableValues}}
){{/isEnum}}{{^isEnum}}{{#description}} )
// 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}}}: {},
{{/enumVars}}
{{/allowableValues}}
}
// IsValid return true if the value is valid for the enum, false otherwise
func (v {{{classname}}}) IsValid() bool {
_, ok := valid{{{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) {
ev := {{{classname}}}(v)
if ev.IsValid() {
return ev, nil
} else {
return "", fmt.Errorf("invalid value '%v' for {{{classname}}}: valid values are %v", v, Allowed{{{classname}}}EnumValues)
}
}
{{/isEnum}}{{^isEnum}}{{#description}}
// {{classname}} - {{{description}}}{{/description}} // {{classname}} - {{{description}}}{{/description}}
type {{classname}} struct { type {{classname}} struct {
{{#parent}} {{#parent}}

View File

@ -157,6 +157,52 @@ paths:
- petstore_auth: - petstore_auth:
- 'read:pets' - 'read:pets'
deprecated: true 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}': '/pet/{petId}':
get: get:
tags: tags:
@ -851,6 +897,20 @@ components:
- sold - sold
xml: xml:
name: Pet name: Pet
Species:
title: The species of a pet
type: string
enum:
- cat
- dog
- fish
- goat
- pig
Gender:
type: string
enum:
- male
- female
ApiResponse: ApiResponse:
title: An uploaded response title: An uploaded response
description: Describes the result of uploading an image resource description: Describes the result of uploading an image resource

View File

@ -144,7 +144,10 @@ func (c *PetAPIController) DeletePet(w http.ResponseWriter, r *http.Request) {
// FindPetsByStatus - Finds Pets by status // FindPetsByStatus - Finds Pets by status
func (c *PetAPIController) FindPetsByStatus(w http.ResponseWriter, r *http.Request) { func (c *PetAPIController) FindPetsByStatus(w http.ResponseWriter, r *http.Request) {
query := r.URL.Query() 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) result, err := c.service.FindPetsByStatus(r.Context(), statusParam)
// If an error occurred, encode the error with the status code // If an error occurred, encode the error with the status code
if err != nil { if err != nil {
@ -159,7 +162,10 @@ func (c *PetAPIController) FindPetsByStatus(w http.ResponseWriter, r *http.Reque
// Deprecated // Deprecated
func (c *PetAPIController) FindPetsByTags(w http.ResponseWriter, r *http.Request) { func (c *PetAPIController) FindPetsByTags(w http.ResponseWriter, r *http.Request) {
query := r.URL.Query() 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) result, err := c.service.FindPetsByTags(r.Context(), tagsParam)
// If an error occurred, encode the error with the status code // If an error occurred, encode the error with the status code
if err != nil { if err != nil {

View File

@ -16,10 +16,12 @@ go/logger.go
go/model_an_object.go go/model_an_object.go
go/model_api_response.go go/model_api_response.go
go/model_category.go go/model_category.go
go/model_gender.go
go/model_order.go go/model_order.go
go/model_order_info.go go/model_order_info.go
go/model_pet.go go/model_pet.go
go/model_special_info.go go/model_special_info.go
go/model_species.go
go/model_tag.go go/model_tag.go
go/model_user.go go/model_user.go
go/routers.go go/routers.go

View File

@ -158,6 +158,54 @@ paths:
summary: Finds Pets by tags summary: Finds Pets by tags
tags: tags:
- pet - 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}: /pet/{petId}:
delete: delete:
description: "" description: ""
@ -1020,6 +1068,20 @@ components:
type: object type: object
xml: xml:
name: Pet name: Pet
Species:
enum:
- cat
- dog
- fish
- goat
- pig
title: The species of a pet
type: string
Gender:
enum:
- male
- female
type: string
ApiResponse: ApiResponse:
description: Describes the result of uploading an image resource description: Describes the result of uploading an image resource
example: example:

View File

@ -23,6 +23,7 @@ import (
type PetAPIRouter interface { type PetAPIRouter interface {
AddPet(http.ResponseWriter, *http.Request) AddPet(http.ResponseWriter, *http.Request)
DeletePet(http.ResponseWriter, *http.Request) DeletePet(http.ResponseWriter, *http.Request)
FilterPetsByCategory(http.ResponseWriter, *http.Request)
FindPetsByStatus(http.ResponseWriter, *http.Request) FindPetsByStatus(http.ResponseWriter, *http.Request)
// Deprecated // Deprecated
FindPetsByTags(http.ResponseWriter, *http.Request) FindPetsByTags(http.ResponseWriter, *http.Request)
@ -63,6 +64,7 @@ type UserAPIRouter interface {
type PetAPIServicer interface { type PetAPIServicer interface {
AddPet(context.Context, Pet) (ImplResponse, error) AddPet(context.Context, Pet) (ImplResponse, error)
DeletePet(context.Context, int64, string) (ImplResponse, error) DeletePet(context.Context, int64, string) (ImplResponse, error)
FilterPetsByCategory(context.Context, Gender, Species, []Species) (ImplResponse, error)
FindPetsByStatus(context.Context, []string) (ImplResponse, error) FindPetsByStatus(context.Context, []string) (ImplResponse, error)
// Deprecated // Deprecated
FindPetsByTags(context.Context, []string) (ImplResponse, error) FindPetsByTags(context.Context, []string) (ImplResponse, error)

View File

@ -60,6 +60,11 @@ func (c *PetAPIController) Routes() Routes {
"/v2/pet/{petId}", "/v2/pet/{petId}",
c.DeletePet, c.DeletePet,
}, },
"FilterPetsByCategory": Route{
strings.ToUpper("Get"),
"/v2/pet/filterPets/{gender}",
c.FilterPetsByCategory,
},
"FindPetsByStatus": Route{ "FindPetsByStatus": Route{
strings.ToUpper("Get"), strings.ToUpper("Get"),
"/v2/pet/findByStatus", "/v2/pet/findByStatus",
@ -147,10 +152,54 @@ func (c *PetAPIController) DeletePet(w http.ResponseWriter, r *http.Request) {
EncodeJSONResponse(result.Body, &result.Code, result.Headers, w) 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()
genderParam, err := NewGenderFromValue(params["gender"])
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}
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
}
var notSpeciesParam []Species
if query.Has("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)
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 // FindPetsByStatus - Finds Pets by status
func (c *PetAPIController) FindPetsByStatus(w http.ResponseWriter, r *http.Request) { func (c *PetAPIController) FindPetsByStatus(w http.ResponseWriter, r *http.Request) {
query := r.URL.Query() 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) result, err := c.service.FindPetsByStatus(r.Context(), statusParam)
// If an error occurred, encode the error with the status code // If an error occurred, encode the error with the status code
if err != nil { if err != nil {
@ -165,7 +214,10 @@ func (c *PetAPIController) FindPetsByStatus(w http.ResponseWriter, r *http.Reque
// Deprecated // Deprecated
func (c *PetAPIController) FindPetsByTags(w http.ResponseWriter, r *http.Request) { func (c *PetAPIController) FindPetsByTags(w http.ResponseWriter, r *http.Request) {
query := r.URL.Query() 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) result, err := c.service.FindPetsByTags(r.Context(), tagsParam)
// If an error occurred, encode the error with the status code // If an error occurred, encode the error with the status code
if err != nil { if err != nil {

View File

@ -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") 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 // FindPetsByStatus - Finds Pets by status
func (s *PetAPIService) FindPetsByStatus(ctx context.Context, status []string) (ImplResponse, error) { func (s *PetAPIService) FindPetsByStatus(ctx context.Context, status []string) (ImplResponse, error) {
// TODO - update FindPetsByStatus with the required logic for this service method. // TODO - update FindPetsByStatus with the required logic for this service method.

View File

@ -0,0 +1,66 @@
/*
* 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"
)
// 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 := validGenderEnumValues[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) {
ev := Gender(v)
if ev.IsValid() {
return ev, nil
} else {
return "", 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
}

View File

@ -0,0 +1,75 @@
/*
* 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"
)
// 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": {},
"goat": {},
"pig": {},
}
// IsValid return true if the value is valid for the enum, false otherwise
func (v Species) IsValid() bool {
_, ok := validSpeciesEnumValues[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) {
ev := Species(v)
if ev.IsValid() {
return ev, nil
} else {
return "", 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
}

View File

@ -16,10 +16,12 @@ go/logger.go
go/model_an_object.go go/model_an_object.go
go/model_api_response.go go/model_api_response.go
go/model_category.go go/model_category.go
go/model_gender.go
go/model_order.go go/model_order.go
go/model_order_info.go go/model_order_info.go
go/model_pet.go go/model_pet.go
go/model_special_info.go go/model_special_info.go
go/model_species.go
go/model_tag.go go/model_tag.go
go/model_user.go go/model_user.go
go/routers.go go/routers.go

View File

@ -158,6 +158,54 @@ paths:
summary: Finds Pets by tags summary: Finds Pets by tags
tags: tags:
- pet - 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}: /pet/{petId}:
delete: delete:
description: "" description: ""
@ -1020,6 +1068,20 @@ components:
type: object type: object
xml: xml:
name: Pet name: Pet
Species:
enum:
- cat
- dog
- fish
- goat
- pig
title: The species of a pet
type: string
Gender:
enum:
- male
- female
type: string
ApiResponse: ApiResponse:
description: Describes the result of uploading an image resource description: Describes the result of uploading an image resource
example: example:

View File

@ -23,6 +23,7 @@ import (
type PetAPIRouter interface { type PetAPIRouter interface {
AddPet(http.ResponseWriter, *http.Request) AddPet(http.ResponseWriter, *http.Request)
DeletePet(http.ResponseWriter, *http.Request) DeletePet(http.ResponseWriter, *http.Request)
FilterPetsByCategory(http.ResponseWriter, *http.Request)
FindPetsByStatus(http.ResponseWriter, *http.Request) FindPetsByStatus(http.ResponseWriter, *http.Request)
// Deprecated // Deprecated
FindPetsByTags(http.ResponseWriter, *http.Request) FindPetsByTags(http.ResponseWriter, *http.Request)
@ -63,6 +64,7 @@ type UserAPIRouter interface {
type PetAPIServicer interface { type PetAPIServicer interface {
AddPet(context.Context, Pet) (ImplResponse, error) AddPet(context.Context, Pet) (ImplResponse, error)
DeletePet(context.Context, int64, string) (ImplResponse, error) DeletePet(context.Context, int64, string) (ImplResponse, error)
FilterPetsByCategory(context.Context, Gender, Species, []Species) (ImplResponse, error)
FindPetsByStatus(context.Context, []string) (ImplResponse, error) FindPetsByStatus(context.Context, []string) (ImplResponse, error)
// Deprecated // Deprecated
FindPetsByTags(context.Context, []string) (ImplResponse, error) FindPetsByTags(context.Context, []string) (ImplResponse, error)

View File

@ -60,6 +60,11 @@ func (c *PetAPIController) Routes() Routes {
"/v2/pet/{petId}", "/v2/pet/{petId}",
c.DeletePet, c.DeletePet,
}, },
"FilterPetsByCategory": Route{
strings.ToUpper("Get"),
"/v2/pet/filterPets/{gender}",
c.FilterPetsByCategory,
},
"FindPetsByStatus": Route{ "FindPetsByStatus": Route{
strings.ToUpper("Get"), strings.ToUpper("Get"),
"/v2/pet/findByStatus", "/v2/pet/findByStatus",
@ -146,10 +151,53 @@ func (c *PetAPIController) DeletePet(w http.ResponseWriter, r *http.Request) {
EncodeJSONResponse(result.Body, &result.Code, result.Headers, w) 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()
genderParam, err := NewGenderFromValue(chi.URLParam(r, "gender"))
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}
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
}
var notSpeciesParam []Species
if query.Has("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)
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 // FindPetsByStatus - Finds Pets by status
func (c *PetAPIController) FindPetsByStatus(w http.ResponseWriter, r *http.Request) { func (c *PetAPIController) FindPetsByStatus(w http.ResponseWriter, r *http.Request) {
query := r.URL.Query() 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) result, err := c.service.FindPetsByStatus(r.Context(), statusParam)
// If an error occurred, encode the error with the status code // If an error occurred, encode the error with the status code
if err != nil { if err != nil {
@ -164,7 +212,10 @@ func (c *PetAPIController) FindPetsByStatus(w http.ResponseWriter, r *http.Reque
// Deprecated // Deprecated
func (c *PetAPIController) FindPetsByTags(w http.ResponseWriter, r *http.Request) { func (c *PetAPIController) FindPetsByTags(w http.ResponseWriter, r *http.Request) {
query := r.URL.Query() 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) result, err := c.service.FindPetsByTags(r.Context(), tagsParam)
// If an error occurred, encode the error with the status code // If an error occurred, encode the error with the status code
if err != nil { if err != nil {

View File

@ -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") 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 // FindPetsByStatus - Finds Pets by status
func (s *PetAPIService) FindPetsByStatus(ctx context.Context, status []string) (ImplResponse, error) { func (s *PetAPIService) FindPetsByStatus(ctx context.Context, status []string) (ImplResponse, error) {
// TODO - update FindPetsByStatus with the required logic for this service method. // TODO - update FindPetsByStatus with the required logic for this service method.

View File

@ -0,0 +1,66 @@
/*
* 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"
)
// 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 := validGenderEnumValues[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) {
ev := Gender(v)
if ev.IsValid() {
return ev, nil
} else {
return "", 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
}

View File

@ -0,0 +1,75 @@
/*
* 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"
)
// 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": {},
"goat": {},
"pig": {},
}
// IsValid return true if the value is valid for the enum, false otherwise
func (v Species) IsValid() bool {
_, ok := validSpeciesEnumValues[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) {
ev := Species(v)
if ev.IsValid() {
return ev, nil
} else {
return "", 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
}