Skip to content

Commit 1dd9590

Browse files
authored
[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
1 parent d1fa38e commit 1dd9590

File tree

19 files changed

+718
-9
lines changed

19 files changed

+718
-9
lines changed

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/GoServerCodegen.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ public ModelsMap postProcessModels(ModelsMap objs) {
301301

302302
CodegenModel model = m.getModel();
303303
if (model.isEnum) {
304+
imports.add(createMapping("import", "fmt"));
304305
continue;
305306
}
306307

modules/openapi-generator/src/main/resources/go-server/controller-api.mustache

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,16 @@ func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Re
173173
{{^isDouble}}
174174
{{^isLong}}
175175
{{^isInteger}}
176+
{{^isEnumOrRef}}
176177
{{paramName}}Param := {{#routers}}{{#mux}}params["{{baseName}}"]{{/mux}}{{#chi}}chi.URLParam(r, "{{baseName}}"){{/chi}}{{/routers}}
178+
{{/isEnumOrRef}}
179+
{{#isEnumOrRef}}
180+
{{paramName}}Param, err := New{{dataType}}FromValue({{#routers}}{{#mux}}params["{{baseName}}"]{{/mux}}{{#chi}}chi.URLParam(r, "{{baseName}}"){{/chi}}{{/routers}})
181+
if err != nil {
182+
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
183+
return
184+
}
185+
{{/isEnumOrRef}}
177186
{{/isInteger}}
178187
{{/isLong}}
179188
{{/isDouble}}
@@ -329,7 +338,27 @@ func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Re
329338
{{^items.isDouble}}
330339
{{^items.isLong}}
331340
{{^items.isInteger}}
332-
{{paramName}}Param := strings.Split(query.Get("{{baseName}}"), ",")
341+
{{^items.isEnumRef}}
342+
var {{paramName}}Param []string
343+
if query.Has("{{baseName}}") {
344+
{{paramName}}Param = strings.Split(query.Get("{{baseName}}"), ",")
345+
}
346+
{{/items.isEnumRef}}
347+
{{#items.isEnumRef}}
348+
var {{paramName}}Param []{{items.dataType}}
349+
if query.Has("{{baseName}}") {
350+
paramSplits := strings.Split(query.Get("{{baseName}}"), ",")
351+
{{paramName}}Param = make([]{{items.dataType}}, 0, len(paramSplits))
352+
for _, param := range paramSplits {
353+
paramEnum, err := New{{items.dataType}}FromValue(param)
354+
if err != nil {
355+
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
356+
return
357+
}
358+
{{paramName}}Param = append({{paramName}}Param, paramEnum)
359+
}
360+
}
361+
{{/items.isEnumRef}}
333362
{{/items.isInteger}}
334363
{{/items.isLong}}
335364
{{/items.isDouble}}
@@ -346,11 +375,42 @@ func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Re
346375
{{#defaultValue}}
347376
{{paramName}}Param := "{{defaultValue}}"
348377
if query.Has("{{baseName}}") {
349-
{{paramName}}Param = query.Get("{{baseName}}")
378+
{{paramName}}Param = {{^isString}}{{dataType}}( {{/isString}}query.Get("{{baseName}}"){{^isString}} ){{/isString}}
350379
}
351380
{{/defaultValue}}
352381
{{^defaultValue}}
382+
{{^required}}
383+
var {{paramName}}Param {{dataType}}
384+
if query.Has("{{baseName}}") {
385+
{{^isEnumOrRef}}
386+
{{paramName}}Param = query.Get("{{baseName}}")
387+
{{/isEnumOrRef}}
388+
{{#isEnumOrRef}}
389+
var err error
390+
{{paramName}}Param, err = New{{dataType}}FromValue(query.Get("{{baseName}}"))
391+
if err != nil {
392+
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
393+
return
394+
}
395+
{{/isEnumOrRef}}
396+
}
397+
{{/required}}
398+
{{#required}}
399+
{{^isEnumOrRef}}
353400
{{paramName}}Param := query.Get("{{baseName}}")
401+
{{/isEnumOrRef}}
402+
{{#isEnumOrRef}}
403+
if !query.Has("{{baseName}}"){
404+
c.errorHandler(w, r, &RequiredError{"{{baseName}}"}, nil)
405+
return
406+
}
407+
{{paramName}}Param, err := New{{dataType}}FromValue(query.Get("{{baseName}}"))
408+
if err != nil {
409+
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
410+
return
411+
}
412+
{{/isEnumOrRef}}
413+
{{/required}}
354414
{{/defaultValue}}
355415
{{/isArray}}
356416
{{/isBoolean}}

modules/openapi-generator/src/main/resources/go-server/model.mustache

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,44 @@ const (
1717
{{#enumClassPrefix}}{{{classname.toUpperCase}}}_{{/enumClassPrefix}}{{name}} {{{classname}}} = {{{value}}}
1818
{{/enumVars}}
1919
{{/allowableValues}}
20-
){{/isEnum}}{{^isEnum}}{{#description}}
20+
)
21+
22+
// Allowed{{{classname}}}EnumValues is all the allowed values of {{{classname}}} enum
23+
var Allowed{{{classname}}}EnumValues = []{{{classname}}}{
24+
{{#allowableValues}}
25+
{{#enumVars}}
26+
{{{value}}},
27+
{{/enumVars}}
28+
{{/allowableValues}}
29+
}
30+
31+
// valid{{{classname}}}EnumValue provides a map of {{classname}}s for fast verification of use input
32+
var valid{{{classname}}}EnumValues = map[{{{classname}}}]struct{}{
33+
{{#allowableValues}}
34+
{{#enumVars}}
35+
{{{value}}}: {},
36+
{{/enumVars}}
37+
{{/allowableValues}}
38+
}
39+
40+
// IsValid return true if the value is valid for the enum, false otherwise
41+
func (v {{{classname}}}) IsValid() bool {
42+
_, ok := valid{{{classname}}}EnumValues[v]
43+
return ok
44+
}
45+
46+
// New{{{classname}}}FromValue returns a pointer to a valid {{{classname}}}
47+
// for the value passed as argument, or an error if the value passed is not allowed by the enum
48+
func New{{{classname}}}FromValue(v {{{format}}}{{^format}}{{dataType}}{{/format}}) ({{{classname}}}, error) {
49+
ev := {{{classname}}}(v)
50+
if ev.IsValid() {
51+
return ev, nil
52+
} else {
53+
return "", fmt.Errorf("invalid value '%v' for {{{classname}}}: valid values are %v", v, Allowed{{{classname}}}EnumValues)
54+
}
55+
}
56+
57+
{{/isEnum}}{{^isEnum}}{{#description}}
2158
// {{classname}} - {{{description}}}{{/description}}
2259
type {{classname}} struct {
2360
{{#parent}}

modules/openapi-generator/src/test/resources/3_0/go-server/petstore.yaml

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,52 @@ paths:
157157
- petstore_auth:
158158
- 'read:pets'
159159
deprecated: true
160+
'/pet/filterPets/{gender}':
161+
get:
162+
tags:
163+
- pet
164+
summary: Finds Pets
165+
operationId: filterPetsByCategory
166+
parameters:
167+
- name: gender
168+
in: path
169+
required: true
170+
schema:
171+
$ref: '#/components/schemas/Gender'
172+
- name: species
173+
in: query
174+
description: Species to filter by
175+
required: true
176+
style: form
177+
explode: false
178+
schema:
179+
$ref: '#/components/schemas/Species'
180+
- name: notSpecies
181+
in: query
182+
description: Species to omit from results
183+
required: false
184+
style: form
185+
explode: false
186+
schema:
187+
type: array
188+
items:
189+
$ref: '#/components/schemas/Species'
190+
responses:
191+
'200':
192+
description: successful operation
193+
content:
194+
application/xml:
195+
schema:
196+
type: array
197+
items:
198+
$ref: '#/components/schemas/Pet'
199+
application/json:
200+
schema:
201+
type: array
202+
items:
203+
$ref: '#/components/schemas/Pet'
204+
'400':
205+
description: Invalid species value
160206
'/pet/{petId}':
161207
get:
162208
tags:
@@ -851,6 +897,20 @@ components:
851897
- sold
852898
xml:
853899
name: Pet
900+
Species:
901+
title: The species of a pet
902+
type: string
903+
enum:
904+
- cat
905+
- dog
906+
- fish
907+
- goat
908+
- pig
909+
Gender:
910+
type: string
911+
enum:
912+
- male
913+
- female
854914
ApiResponse:
855915
title: An uploaded response
856916
description: Describes the result of uploading an image resource

samples/openapi3/server/petstore/go/go-petstore/go/api_pet.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,10 @@ func (c *PetAPIController) DeletePet(w http.ResponseWriter, r *http.Request) {
144144
// FindPetsByStatus - Finds Pets by status
145145
func (c *PetAPIController) FindPetsByStatus(w http.ResponseWriter, r *http.Request) {
146146
query := r.URL.Query()
147-
statusParam := strings.Split(query.Get("status"), ",")
147+
var statusParam []string
148+
if query.Has("status") {
149+
statusParam = strings.Split(query.Get("status"), ",")
150+
}
148151
result, err := c.service.FindPetsByStatus(r.Context(), statusParam)
149152
// If an error occurred, encode the error with the status code
150153
if err != nil {
@@ -159,7 +162,10 @@ func (c *PetAPIController) FindPetsByStatus(w http.ResponseWriter, r *http.Reque
159162
// Deprecated
160163
func (c *PetAPIController) FindPetsByTags(w http.ResponseWriter, r *http.Request) {
161164
query := r.URL.Query()
162-
tagsParam := strings.Split(query.Get("tags"), ",")
165+
var tagsParam []string
166+
if query.Has("tags") {
167+
tagsParam = strings.Split(query.Get("tags"), ",")
168+
}
163169
result, err := c.service.FindPetsByTags(r.Context(), tagsParam)
164170
// If an error occurred, encode the error with the status code
165171
if err != nil {

samples/server/petstore/go-api-server/.openapi-generator/FILES

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@ go/logger.go
1616
go/model_an_object.go
1717
go/model_api_response.go
1818
go/model_category.go
19+
go/model_gender.go
1920
go/model_order.go
2021
go/model_order_info.go
2122
go/model_pet.go
2223
go/model_special_info.go
24+
go/model_species.go
2325
go/model_tag.go
2426
go/model_user.go
2527
go/routers.go

samples/server/petstore/go-api-server/api/openapi.yaml

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,54 @@ paths:
158158
summary: Finds Pets by tags
159159
tags:
160160
- pet
161+
/pet/filterPets/{gender}:
162+
get:
163+
operationId: filterPetsByCategory
164+
parameters:
165+
- explode: false
166+
in: path
167+
name: gender
168+
required: true
169+
schema:
170+
$ref: '#/components/schemas/Gender'
171+
style: simple
172+
- description: Species to filter by
173+
explode: false
174+
in: query
175+
name: species
176+
required: true
177+
schema:
178+
$ref: '#/components/schemas/Species'
179+
style: form
180+
- description: Species to omit from results
181+
explode: false
182+
in: query
183+
name: notSpecies
184+
required: false
185+
schema:
186+
items:
187+
$ref: '#/components/schemas/Species'
188+
type: array
189+
style: form
190+
responses:
191+
"200":
192+
content:
193+
application/xml:
194+
schema:
195+
items:
196+
$ref: '#/components/schemas/Pet'
197+
type: array
198+
application/json:
199+
schema:
200+
items:
201+
$ref: '#/components/schemas/Pet'
202+
type: array
203+
description: successful operation
204+
"400":
205+
description: Invalid species value
206+
summary: Finds Pets
207+
tags:
208+
- pet
161209
/pet/{petId}:
162210
delete:
163211
description: ""
@@ -1020,6 +1068,20 @@ components:
10201068
type: object
10211069
xml:
10221070
name: Pet
1071+
Species:
1072+
enum:
1073+
- cat
1074+
- dog
1075+
- fish
1076+
- goat
1077+
- pig
1078+
title: The species of a pet
1079+
type: string
1080+
Gender:
1081+
enum:
1082+
- male
1083+
- female
1084+
type: string
10231085
ApiResponse:
10241086
description: Describes the result of uploading an image resource
10251087
example:

samples/server/petstore/go-api-server/go/api.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
type PetAPIRouter interface {
2424
AddPet(http.ResponseWriter, *http.Request)
2525
DeletePet(http.ResponseWriter, *http.Request)
26+
FilterPetsByCategory(http.ResponseWriter, *http.Request)
2627
FindPetsByStatus(http.ResponseWriter, *http.Request)
2728
// Deprecated
2829
FindPetsByTags(http.ResponseWriter, *http.Request)
@@ -63,6 +64,7 @@ type UserAPIRouter interface {
6364
type PetAPIServicer interface {
6465
AddPet(context.Context, Pet) (ImplResponse, error)
6566
DeletePet(context.Context, int64, string) (ImplResponse, error)
67+
FilterPetsByCategory(context.Context, Gender, Species, []Species) (ImplResponse, error)
6668
FindPetsByStatus(context.Context, []string) (ImplResponse, error)
6769
// Deprecated
6870
FindPetsByTags(context.Context, []string) (ImplResponse, error)

0 commit comments

Comments
 (0)