[BUG][GO Server] Optional or invalid boolean query params are not properly checked.
Created by: avbenavides
Bug Report Checklist
- [x ] Have you provided a full/minimal spec to reproduce the issue?
- [ x] Have you validated the input using an OpenAPI validator (example)?
- [ x] Have you tested with the latest master to confirm the issue still exists?
- [x ] Have you searched for related issues/PRs?
- [ x] What's the actual output vs expected output?
-
[Optional] Sponsorship to speed up the bug fix or feature request (example)
Description
When the payload have one or more optional query param booleans and is not set or set incorrectly, the server returns 500 response with no body and it swallows the error. There's nothing in the logs either to indicate what went wrong.
The root cause is that the parseBoolParameter
function does not check if the value is valid and the router function does not call the errorHandler
.
openapi-generator version
5.3.0
OpenAPI declaration file content or url
openapi: 3.0.2
info:
description: example
title: test
version: 0.0.1
paths:
/reports:
get:
description: sampleBug
operationId: sampleBug
parameters:
- description: none
explode: true
in: query
name: fromStart
required: false
schema:
default: false
type: boolean
style: form
responses:
"202":
content:
application/json:
schema:
type: string
description: OK
"400":
content:
application/problem+json:
schema:
type: string
description: Error
"500":
content:
application/problem+json:
schema:
type: string
description: Error
summary: Update
Generation Details
Use the openapi-generator-cli bash script
openapi-generator-cli generate -i spec.yaml -g go-server --enable-post-process-file -o src/ -p featureCORS=true,packageName=test,packageVersion=0.0.1
api_default.go
...
// SampleBug - sampleBug
func (c *DefaultApiController) SampleBug(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
query := r.URL.Query()
fromStartParam, err := parseBoolParameter(query.Get("fromStart"))
if err != nil {
w.WriteHeader(500)
return
}
result, err := c.service.SampleBug(r.Context(), fromStartParam)
// 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, w)
}
...
router.go
...
// parseBoolParameter parses a string parameter to a bool
func parseBoolParameter(param string) (bool, error) {
val, err := strconv.ParseBool(param)
if err != nil {
return false, err
}
return bool(val), nil
}
...
Steps to reproduce
Start the server and then make a request
# Example without optional parameter. Expected to use the default
curl localhost:8080/api/v1/reports
# Example with invalid parameter (should return a 4XX)
curl localhost:8080/api/v1/reports?fromStart=Yes
Related issues/PRs
N/A
Suggest a fix
For optional boolean with default, it requires a new function
routers.go
...
// parseOptionalBoolParameter parses an optional string parameter to a bool
func parseOptionalBoolParameter(param string, defaultVaule bool) (bool, error) {
if IsZeroValue(param) {
return defaultVaule, nil
}
val, err := strconv.ParseBool(param)
if err != nil {
return false, err
}
return val, nil
}
...
api_default.go
...
// SampleBug - sampleBug
func (c *DefaultApiController) SampleBug(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
query := r.URL.Query()
fromStartParam, err := parseOptionalBoolParameter(query.Get("fromStart"), false)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}
result, err := c.service.SampleBug(r.Context(), fromStartParam)
// 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, w)
}
...
For required boolean, it requires to update parseBoolParameter routers.go
...
// parseBoolParameter parses an required string parameter to a bool
func parseBoolParameter(param string) (bool, error) {
if IsZeroValue(param) {
return false, errors.New(errMsgRequiredMissing)
}
val, err := strconv.ParseBool(param)
if err != nil {
return false, err
}
return val, nil
}
...
api_default.go
...
// SampleBug - sampleBug
func (c *DefaultApiController) SampleBug(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
query := r.URL.Query()
fromStartParam, err := parseBoolParameter(query.Get("fromStart"))
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}
result, err := c.service.SampleBug(r.Context(), fromStartParam)
// 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, w)
}
...