swagger-api / swagger-api/swagger-codegen
[GO] Error generating client, response body is consumed and returned as an empty pointer
Nobody has claimed this yet.
- Dominant language
- Mustache
- Stars
- 17.8k
- Forks
- 6k
- PR merge metrics
- No merged PRs in 30d
Description
Description
When generating go code from a swagger json like this:
"/api/v2/projects/": {
"get": {
"description": "~edited",
"operationId": "Projects_projects_list",
"parameters": [
{
"description": "A page number within the paginated result set.",
"in": "query",
"name": "page",
"required": false,
"type": "integer"
},
{
"description": "Number of results to return per page.",
"in": "query",
"name": "page_size",
"required": false,
"type": "integer"
},
{
"description": "A search term.",
"in": "query",
"name": "search",
"required": false,
"type": "string"
}
],
"responses": {
"200": {
"description": ""
}
},
"summary": " List Projects",
"tags": [
"Projects"
]
},
...
the following go code is generated:
func (a *ProjectsApiService) ProjectsProjectsList(ctx context.Context, localVarOptionals *ProjectsApiProjectsProjectsListOpts) (*http.Response, error) {
var (
localVarHttpMethod = strings.ToUpper("Get")
localVarPostBody interface{}
localVarFileName string
localVarFileBytes []byte
)
// create path and map variables
localVarPath := a.client.cfg.BasePath + "/api/v2/projects/"
localVarHeaderParams := make(map[string]string)
localVarQueryParams := url.Values{}
localVarFormParams := url.Values{}
if localVarOptionals != nil && localVarOptionals.Page.IsSet() {
localVarQueryParams.Add("page", parameterToString(localVarOptionals.Page.Value(), ""))
}
if localVarOptionals != nil && localVarOptionals.PageSize.IsSet() {
localVarQueryParams.Add("page_size", parameterToString(localVarOptionals.PageSize.Value(), ""))
}
if localVarOptionals != nil && localVarOptionals.Search.IsSet() {
localVarQueryParams.Add("search", parameterToString(localVarOptionals.Search.Value(), ""))
}
// to determine the Content-Type header
localVarHttpContentTypes := []string{"application/json"}
// set Content-Type header
localVarHttpContentType := selectHeaderContentType(localVarHttpContentTypes)
if localVarHttpContentType != "" {
localVarHeaderParams["Content-Type"] = localVarHttpContentType
}
// to determine the Accept header
localVarHttpHeaderAccepts := []string{}
// set Accept header
localVarHttpHeaderAccept := selectHeaderAccept(localVarHttpHeaderAccepts)
if localVarHttpHeaderAccept != "" {
localVarHeaderParams["Accept"] = localVarHttpHeaderAccept
}
r, err := a.client.prepareRequest(ctx, localVarPath, localVarHttpMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFileName, localVarFileBytes)
if err != nil {
return nil, err
}
localVarHttpResponse, err := a.client.callAPI(r)
if err != nil || localVarHttpResponse == nil {
return localVarHttpResponse, err
}
localVarBody, err := ioutil.ReadAll(localVarHttpResponse.Body) //THE PROBLEM IS HERE
localVarHttpResponse.Body.Close()
if err != nil {
return localVarHttpResponse, err
}
if localVarHttpResponse.StatusCode >= 300 {
newErr := GenericSwaggerError{
body: localVarBody,
error: localVarHttpResponse.Status,
}
return localVarHttpResponse, newErr
}
return localVarHttpResponse, nil //AND HERE
}
The problem in this function is that this line localVarBody, err := ioutil.ReadAll(localVarHttpResponse.Body) read the body of the response pointer and leave the localVarHttpResponse.Body empty. As a consequence the return localVarHttpResponse, nil returns the pointer to the response with the empty body.
This seems the case for any resource generated.
Swagger-codegen version
3.0.20
Swagger declaration file content or url
https://github.com/Roviluca/awx-go-autogenerated/blob/main/swagger.json
Command line used for generation
swagger-codegen generate -i ./swagger.json -l go -o ./test-codegen
Suggest a fix/enhancement
You can consume the content of the body only if needed by the return by moving the ReadAll inside the if checking for the response code >300.
if localVarHttpResponse.StatusCode >= 300 {
localVarBody, err := ioutil.ReadAll(localVarHttpResponse.Body)
localVarHttpResponse.Body.Close()
if err != nil {
return localVarHttpResponse, err
}
newErr := GenericSwaggerError{
body: localVarBody,
error: localVarHttpResponse.Status,
}
return localVarHttpResponse, newErr
}
return localVarHttpResponse, nil```
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the Go client generation path invoked by swagger-codegen generate -i ./swagger.json -l go -o ./test-codegen, then trace the generated ProjectsProjectsList response handling and its callAPI entry point. Reproduce the behavior using the linked Swagger declaration and verify that successful responses retain a readable body while error responses still expose their body and status.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- devtools, tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100