Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[go-server] Add ability to handle nullable query param #17051

Closed
wants to merge 25 commits into from
Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
e066b8b
Add nullable to query param
lwj5 Nov 13, 2023
363b330
Add nullable to query param
lwj5 Nov 13, 2023
432d7ba
Merge branch 'master' into querynull
lwj5 Nov 13, 2023
607766d
Fix generation
lwj5 Nov 13, 2023
e62a559
Fix generation
lwj5 Nov 13, 2023
0387d4e
update lombok dep to newer version (#17053)
wing328 Nov 14, 2023
ea7fc16
Fix NPE in request body (#17055)
wing328 Nov 14, 2023
b3fc40f
[Java][okhttp-gson] remove unreachable code from templates (#17057)
ctreatma Nov 14, 2023
a9102b8
Retain deprecated in allOf schema handling (#17056)
wing328 Nov 14, 2023
cdc9a5d
disabled GetHashCode generation (#17039)
devhl-labs Nov 14, 2023
f13553b
[python] added handling for boolean content type (#17020)
OliverTetzTT Nov 14, 2023
f8bf9a0
Update base image of Dockerfile (#17007)
litetex Nov 14, 2023
dfc6895
Add socks5 proxy support for OpenAPI generated python client (#16918)
rolf-moz Nov 14, 2023
3070e32
update algoria settings (#17064)
wing328 Nov 14, 2023
225de17
fix: Disable warnings for model_* properties (#17066)
robertschweizer Nov 14, 2023
3f7c9d2
[typescript-axios] Upgrade to axios@^1 (#14518)
segevfiner Nov 14, 2023
6744004
[csharp] Added .net8 (#17075)
devhl-labs Nov 15, 2023
8a52e22
Add passgenau-digital and we-make.ai as OpenAPI Generator users (#17077)
jonasheschl Nov 15, 2023
a682094
[python][Feat] Deserialize error responses (#17038)
robertschweizer Nov 15, 2023
29ea180
[Java][resttemplate] Add test for bearer auth (#17081)
kota65535 Nov 15, 2023
0c3a0a3
update samples
wing328 Nov 15, 2023
54f064b
Use JDK17 images in Dockerfile (#17076)
wing328 Nov 16, 2023
3a137d9
Update to include enum and time
lwj5 Nov 16, 2023
42f151e
fix import
lwj5 Nov 16, 2023
6fa4b16
Regen
lwj5 Dec 5, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,5 @@ type {{classname}}Servicer interface { {{#operations}}{{#operation}}
{{#isDeprecated}}
// Deprecated
{{/isDeprecated}}
{{operationId}}(context.Context{{#allParams}}, {{dataType}}{{/allParams}}) (ImplResponse, error){{/operation}}{{/operations}}
{{operationId}}(context.Context{{#allParams}}, {{#isNullable}}*{{/isNullable}}{{dataType}}{{/allParams}}) (ImplResponse, error){{/operation}}{{/operations}}
}{{/apis}}{{/apiInfo}}
Original file line number Diff line number Diff line change
Expand Up @@ -224,85 +224,171 @@ func (c *{{classname}}Controller) {{nickname}}(w http.ResponseWriter, r *http.Re
{{/required}}
{{/isDateTime}}
{{#isNumber}}
lwj5 marked this conversation as resolved.
Show resolved Hide resolved
{{paramName}}Param, err := parseNumericParameter[float32](
query.Get("{{baseName}}"),{{#defaultValue}}
WithDefaultOrParse[float32]({{defaultValue}}, parseFloat32),{{/defaultValue}}{{^defaultValue}}{{#required}}
WithRequire[float32](parseFloat32),{{/required}}{{/defaultValue}}{{^defaultValue}}{{^required}}
WithParse[float32](parseFloat32),{{/required}}{{/defaultValue}}{{#minimum}}
WithMinimum[float32]({{minimum}}),{{/minimum}}{{#maximum}}
WithMaximum[float32]({{maximum}}),{{/maximum}}
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
var {{paramName}}Param {{#isNullable}}*{{/isNullable}}float32
if query.Has("{{baseName}}") {
param, err := parseNumericParameter[float32](
query.Get("{{baseName}}"),
WithParse[float32](parseFloat32),{{#minimum}}
WithMinimum[float32]({{minimum}}),{{/minimum}}{{#maximum}}
WithMaximum[float32]({{maximum}}),{{/maximum}}
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}

{{paramName}}Param = {{#isNullable}}&{{/isNullable}}param
} else {
{{#required}}
c.errorHandler(w, r, &RequiredError{Field: "{{baseName}}"}, nil)
return
{{/required}}
{{^required}}
{{#defaultValue}}
var param float32 = {{defaultValue}}
{{paramName}}Param = {{#isNullable}}&{{/isNullable}}param
{{/defaultValue}}
{{/required}}
}
{{/isNumber}}
{{#isFloat}}
{{paramName}}Param, err := parseNumericParameter[float32](
query.Get("{{baseName}}"),{{#defaultValue}}
WithDefaultOrParse[float32]({{defaultValue}}, parseFloat32),{{/defaultValue}}{{^defaultValue}}{{#required}}
WithRequire[float32](parseFloat32),{{/required}}{{/defaultValue}}{{^defaultValue}}{{^required}}
WithParse[float32](parseFloat32),{{/required}}{{/defaultValue}}{{#minimum}}
WithMinimum[float32]({{minimum}}),{{/minimum}}{{#maximum}}
WithMaximum[float32]({{maximum}}),{{/maximum}}
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
var {{paramName}}Param {{#isNullable}}*{{/isNullable}}float32
if query.Has("{{baseName}}") {
param, err := parseNumericParameter[float32](
query.Get("{{baseName}}"),
WithParse[float32](parseFloat32),{{#minimum}}
WithMinimum[float32]({{minimum}}),{{/minimum}}{{#maximum}}
WithMaximum[float32]({{maximum}}),{{/maximum}}
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}

{{paramName}}Param = {{#isNullable}}&{{/isNullable}}param
} else {
{{#required}}
c.errorHandler(w, r, &RequiredError{Field: "{{baseName}}"}, nil)
return
{{/required}}
{{^required}}
{{#defaultValue}}
var param float32 = {{defaultValue}}
{{paramName}}Param = {{#isNullable}}&{{/isNullable}}param
{{/defaultValue}}
{{/required}}
}
{{/isFloat}}
{{#isDouble}}
{{paramName}}Param, err := parseNumericParameter[float64](
query.Get("{{baseName}}"),{{#defaultValue}}
WithDefaultOrParse[float64]({{defaultValue}}, parseFloat64),{{/defaultValue}}{{^defaultValue}}{{#required}}
WithRequire[float64](parseFloat64),{{/required}}{{/defaultValue}}{{^defaultValue}}{{^required}}
WithParse[float64](parseFloat64),{{/required}}{{/defaultValue}}{{#minimum}}
WithMinimum[float64]({{minimum}}),{{/minimum}}{{#maximum}}
WithMaximum[float64]({{maximum}}),{{/maximum}}
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
var {{paramName}}Param {{#isNullable}}*{{/isNullable}}float64
if query.Has("{{baseName}}") {
param, err := parseNumericParameter[float64](
query.Get("{{baseName}}"),
WithParse[float64](parseFloat64),{{#minimum}}
WithMinimum[float64]({{minimum}}),{{/minimum}}{{#maximum}}
WithMaximum[float64]({{maximum}}),{{/maximum}}
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}

{{paramName}}Param = {{#isNullable}}&{{/isNullable}}param
} else {
{{#required}}
c.errorHandler(w, r, &RequiredError{Field: "{{baseName}}"}, nil)
return
{{/required}}
{{^required}}
{{#defaultValue}}
var param float64 = {{defaultValue}}
{{paramName}}Param = {{#isNullable}}&{{/isNullable}}param
{{/defaultValue}}
{{/required}}
}
{{/isDouble}}
{{#isLong}}
{{paramName}}Param, err := parseNumericParameter[int64](
query.Get("{{baseName}}"),{{#defaultValue}}
WithDefaultOrParse[int64]({{defaultValue}}, parseInt64),{{/defaultValue}}{{^defaultValue}}{{#required}}
WithRequire[int64](parseInt64),{{/required}}{{/defaultValue}}{{^defaultValue}}{{^required}}
WithParse[int64](parseInt64),{{/required}}{{/defaultValue}}{{#minimum}}
WithMinimum[int64]({{minimum}}),{{/minimum}}{{#maximum}}
WithMaximum[int64]({{maximum}}),{{/maximum}}
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
var {{paramName}}Param {{#isNullable}}*{{/isNullable}}int64
if query.Has("{{baseName}}") {
param, err := parseNumericParameter[int64](
query.Get("{{baseName}}"),
WithParse[int64](parseInt64),{{#minimum}}
WithMinimum[int64]({{minimum}}),{{/minimum}}{{#maximum}}
WithMaximum[int64]({{maximum}}),{{/maximum}}
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}

{{paramName}}Param = {{#isNullable}}&{{/isNullable}}param
} else {
{{#required}}
c.errorHandler(w, r, &RequiredError{Field: "{{baseName}}"}, nil)
return
{{/required}}
{{^required}}
{{#defaultValue}}
var param int64 = {{defaultValue}}
{{paramName}}Param = {{#isNullable}}&{{/isNullable}}param
{{/defaultValue}}
{{/required}}
}
{{/isLong}}
{{#isInteger}}
{{paramName}}Param, err := parseNumericParameter[int32](
query.Get("{{baseName}}"),{{#defaultValue}}
WithDefaultOrParse[int32]({{defaultValue}}, parseInt32),{{/defaultValue}}{{^defaultValue}}{{#required}}
WithRequire[int32](parseInt32),{{/required}}{{/defaultValue}}{{^defaultValue}}{{^required}}
WithParse[int32](parseInt32),{{/required}}{{/defaultValue}}{{#minimum}}
WithMinimum[int32]({{minimum}}),{{/minimum}}{{#maximum}}
WithMaximum[int32]({{maximum}}),{{/maximum}}
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
var {{paramName}}Param {{#isNullable}}*{{/isNullable}}int32
if query.Has("{{baseName}}") {
param, err := parseNumericParameter[int32](
query.Get("{{baseName}}"),
WithParse[int32](parseInt32),{{#minimum}}
WithMinimum[int32]({{minimum}}),{{/minimum}}{{#maximum}}
WithMaximum[int32]({{maximum}}),{{/maximum}}
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}

{{paramName}}Param = {{#isNullable}}&{{/isNullable}}param
} else {
{{#required}}
c.errorHandler(w, r, &RequiredError{Field: "{{baseName}}"}, nil)
return
{{/required}}
{{^required}}
{{#defaultValue}}
var param int32 = {{defaultValue}}
{{paramName}}Param = {{#isNullable}}&{{/isNullable}}param
{{/defaultValue}}
{{/required}}
}
{{/isInteger}}
{{#isBoolean}}
{{paramName}}Param, err := parseBoolParameter(
query.Get("{{baseName}}"),{{#defaultValue}}
WithDefaultOrParse[bool]({{defaultValue}}, parseBool),{{/defaultValue}}{{^defaultValue}}{{#required}}
WithRequire[bool](parseBool),{{/required}}{{/defaultValue}}{{^defaultValue}}{{^required}}
WithParse[bool](parseBool),{{/required}}{{/defaultValue}}
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
var {{paramName}}Param {{#isNullable}}*{{/isNullable}}bool
if query.Has("{{baseName}}") {
param, err := parseBoolParameter(
query.Get("{{baseName}}"),
WithParse[bool](parseBool),{{#minimum}}
WithMinimum[bool]({{minimum}}),{{/minimum}}{{#maximum}}
WithMaximum[bool]({{maximum}}),{{/maximum}}
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}

{{paramName}}Param = {{#isNullable}}&{{/isNullable}}param
} else {
{{#required}}
c.errorHandler(w, r, &RequiredError{Field: "{{baseName}}"}, nil)
return
{{/required}}
{{^required}}
{{#defaultValue}}
var param bool = {{defaultValue}}
{{paramName}}Param = {{#isNullable}}&{{/isNullable}}param
{{/defaultValue}}
{{/required}}
}
{{/isBoolean}}
{{#isArray}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func New{{classname}}Service() {{classname}}Servicer {
{{#isDeprecated}}
// Deprecated
{{/isDeprecated}}
func (s *{{classname}}Service) {{nickname}}(ctx context.Context{{#allParams}}, {{paramName}} {{dataType}}{{/allParams}}) (ImplResponse, error) {
func (s *{{classname}}Service) {{nickname}}(ctx context.Context{{#allParams}}, {{paramName}} {{#isNullable}}*{{/isNullable}}{{dataType}}{{/allParams}}) (ImplResponse, error) {
Copy link
Contributor

@icubbon icubbon Nov 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think isNullable is behaving as you expect it to here. The Pet Store Specs have many non-required params that would show this change but none of them are showing up in this diff.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you provide a specific example? are they marked as nullable?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One specific example from openapi-generator/samples/server/petstore/go-api-server/api/openapi.yaml is the booleanTest query parameter in deleteUser.

- description: boolean query parameter
        explode: true
        in: query
        name: boolean_test
        required: false
        schema:
          type: boolean
        style: form

This should result in the the function signature for deleteUser having a *bool parameter for the function signature in openapi-generator/samples/server/petstore/go-api-server/go/api_user_service.go

There are numerous query parameters in that example file that have optional query parameters.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// TODO - update {{nickname}} with the required logic for this service method.
// Add {{classFilename}}_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation.

Expand Down
120 changes: 78 additions & 42 deletions samples/openapi3/server/petstore/go/go-petstore/go/api_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,13 +178,19 @@ func (c *UserAPIController) DeleteUser(w http.ResponseWriter, r *http.Request) {
c.errorHandler(w, r, &RequiredError{"username"}, nil)
return
}
booleanTestParam, err := parseBoolParameter(
query.Get("boolean_test"),
WithParse[bool](parseBool),
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
var booleanTestParam bool
if query.Has("boolean_test") {
param, err := parseBoolParameter(
query.Get("boolean_test"),
WithParse[bool](parseBool),
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}

booleanTestParam = param
} else {
}
result, err := c.service.DeleteUser(r.Context(), usernameParam, booleanTestParam)
// If an error occurred, encode the error with the status code
Expand Down Expand Up @@ -218,45 +224,75 @@ func (c *UserAPIController) LoginUser(w http.ResponseWriter, r *http.Request) {
query := r.URL.Query()
usernameParam := query.Get("username")
passwordParam := query.Get("password")
int32TestParam, err := parseNumericParameter[int32](
query.Get("int32_test"),
WithParse[int32](parseInt32),
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
var int32TestParam int32
if query.Has("int32_test") {
param, err := parseNumericParameter[int32](
query.Get("int32_test"),
WithParse[int32](parseInt32),
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}

int32TestParam = param
} else {
}
int64TestParam, err := parseNumericParameter[int64](
query.Get("int64_test"),
WithParse[int64](parseInt64),
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
var int64TestParam int64
if query.Has("int64_test") {
param, err := parseNumericParameter[int64](
query.Get("int64_test"),
WithParse[int64](parseInt64),
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}

int64TestParam = param
} else {
}
float32TestParam, err := parseNumericParameter[float32](
query.Get("float32_test"),
WithParse[float32](parseFloat32),
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
var float32TestParam float32
if query.Has("float32_test") {
param, err := parseNumericParameter[float32](
query.Get("float32_test"),
WithParse[float32](parseFloat32),
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}

float32TestParam = param
} else {
}
float64TestParam, err := parseNumericParameter[float64](
query.Get("float64_test"),
WithParse[float64](parseFloat64),
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
var float64TestParam float64
if query.Has("float64_test") {
param, err := parseNumericParameter[float64](
query.Get("float64_test"),
WithParse[float64](parseFloat64),
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}

float64TestParam = param
} else {
}
booleanTestParam, err := parseBoolParameter(
query.Get("boolean_test"),
WithParse[bool](parseBool),
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
var booleanTestParam bool
if query.Has("boolean_test") {
param, err := parseBoolParameter(
query.Get("boolean_test"),
WithParse[bool](parseBool),
)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}

booleanTestParam = param
} else {
}
result, err := c.service.LoginUser(r.Context(), usernameParam, passwordParam, int32TestParam, int64TestParam, float32TestParam, float64TestParam, booleanTestParam)
// If an error occurred, encode the error with the status code
Expand Down
Loading
Loading