swagger-api / swagger-api/swagger-codegen

[Golang] Generated client trying to unmarshal non-existent JSON into an **os.File

Open
#4,571 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Client: Go help wanted Issue: Bug
Dominant language
Mustache
Stars
17.8k
Forks
6k
PR merge metrics
No merged PRs in 30d

Description

Hi Folks, pretty new to Swagger so not sure if this is a bug or if I'm just being a dolt...

Description

I have the following endpoint definition, intended to just serve some tar file...

/{service}/{account}/{dsid}:
  get:
      summary: Retrieve an archive
      description: Retrieve an archive
      produces:
        - application/x-tar
      parameters:
        - name: service
          in: path
          description: Service archive resides in
          required: true
          type: string
        - name: account
          in: path
          description: Account archive is registered with
          required: true
          type: string
        - name: dsid
          in: path
          description: Archive Id
          required: true
          type: string
      responses:
        200:
          description: An archive
          schema:
            type: file
        404:
          description: Archive could not be found.

Generated server code fine, my handler just boils down to this...

func (h *Handlers) GetDataset(res http.ResponseWriter, req *http.Request) {
	path := "." + req.URL.Path
	http.ServeFile(res, req, path)
}

I know there are security issues, keeping it simple for now. The server endpoint works fine with curl.

Unfortunately, I'm having trouble with generating client code for accessing this endpoint. Here's what the generator gives me...

func (a DefaultApi) ServiceAccountDsidGet(service string, account string, dsid string) (**os.File, *APIResponse, error) {

	var localVarHttpMethod = strings.ToUpper("Get")
	// create path and map variables
	localVarPath := a.Configuration.BasePath + "/{service}/{account}/{dsid}"
	localVarPath = strings.Replace(localVarPath, "{"+"service"+"}", fmt.Sprintf("%v", service), -1)
	localVarPath = strings.Replace(localVarPath, "{"+"account"+"}", fmt.Sprintf("%v", account), -1)
	localVarPath = strings.Replace(localVarPath, "{"+"dsid"+"}", fmt.Sprintf("%v", dsid), -1)

	localVarHeaderParams := make(map[string]string)
	localVarQueryParams := url.Values{}
	localVarFormParams := make(map[string]string)
	var localVarPostBody interface{}
	var localVarFileName string
	var localVarFileBytes []byte
	// add default headers if any
	for key := range a.Configuration.DefaultHeader {
		localVarHeaderParams[key] = a.Configuration.DefaultHeader[key]
	}

	// to determine the Content-Type header
	localVarHttpContentTypes := []string{}

	// set Content-Type header
	localVarHttpContentType := a.Configuration.APIClient.SelectHeaderContentType(localVarHttpContentTypes)
	if localVarHttpContentType != "" {
		localVarHeaderParams["Content-Type"] = localVarHttpContentType
	}
	// to determine the Accept header
	localVarHttpHeaderAccepts := []string{}

	// set Accept header
	localVarHttpHeaderAccept := a.Configuration.APIClient.SelectHeaderAccept(localVarHttpHeaderAccepts)
	if localVarHttpHeaderAccept != "" {
		localVarHeaderParams["Accept"] = localVarHttpHeaderAccept
	}
	var successPayload = new(*os.File)
	localVarHttpResponse, err := a.Configuration.APIClient.CallAPI(localVarPath, localVarHttpMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFileName, localVarFileBytes)

	var localVarURL, _ = url.Parse(localVarPath)
	localVarURL.RawQuery = localVarQueryParams.Encode()
	var localVarAPIResponse = &APIResponse{Operation: "ServiceAccountDsidGet", Method: localVarHttpMethod, RequestURL: localVarURL.String()}
	if localVarHttpResponse != nil {
		localVarAPIResponse.Response = localVarHttpResponse.RawResponse
		localVarAPIResponse.Payload = localVarHttpResponse.Body()
	}

	if err != nil {
		return successPayload, localVarAPIResponse, err
	}
	err = json.Unmarshal(localVarHttpResponse.Body(), &successPayload)
	return successPayload, localVarAPIResponse, err
}

This consistently fails because of the second to last line. The response body does not contain JSON, it's just file data, therefore it doesn't make sense to try unmarshaling it into the return value. No matter how I fiddle with my definition, I can't seem to convince the generator that the body data shouldn't be JSON.

So, am I coming at this the wrong way, or is there something up with the templates?

Thanks!

Mark

Swagger-codegen version

Generated using swagger editor 2.10.3

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

Reproduce the issue from the supplied Swagger endpoint definition and inspect the Go client generation templates behind DefaultApi.ServiceAccountDsidGet, especially handling for responses with type: file. Run the generated client against the application/x-tar endpoint and verify that archive data is handled without attempting JSON unmarshaling.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.