OpenAPITools / OpenAPITools/openapi-generator

[BUG][GO Server] Optional or invalid boolean query params are not properly checked.

Open
#10,787 2 comments 4 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Issue: Bug
Dominant language
Java
Stars
26.8k
Forks
7.7k
PR merge metrics
PR metrics pending

Description

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)

}
...

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the generated api_default.go and router.go/routers.go examples, then reproduce the behavior using the provided openapi-generator-cli command and curl requests. The work is done when omitted optional booleans use their defaults, invalid values reach errorHandler and return a 4XX response, and required missing values are reported rather than producing an empty 500 response.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
api, backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
50/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.