swagger-api / swagger-api/swagger-codegen

text/plain results in an undefined response type with Golang Swagger

Open
#10,997 1 comment 3 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Mustache
Stars
17.8k
Forks
6k
PR merge metrics
No merged PRs in 30d

Description

Description

Hello, when im generating Golang code for a simple endpoint that returns plain text the generated client runs in an error:
undefined response type . I added the code snippets below.

Swagger-codegen version

2.0

Swagger declaration file content or url
---
swagger: "2.0"
info:
  description: "something"
  version: "v2.6"
  title: "something"
  contact:
    email: "something@something.de"
host: "something.de"
tags:
- name: "administration"
  description: "Meta services"
schemes:
- "https"
- "http"
consumes:
- "application/json"
produces:
- "application/json"
security:
- basicAuth: []
paths:
  /about/version:
    get:
      tags:
      - "administration"
      summary: "current software version"
      description: "Returns the current something version"
      produces:
      - "text/plain"
      parameters: []
      responses:
        "200":
          description: "successful operation"
          schema:
            type: "string"
            example: "1.9.44-04345"
        "400":
          description: "bad request"
          schema:
            $ref: "#/definitions/ErrorMessage"
        "500":
          description: "internal server error"
          schema:
            $ref: "#/definitions/ErrorMessage"
securityDefinitions:
  basicAuth:
    type: "basic"
definitions:
  ErrorMessage:
    type: "object"
    properties:
      errorMessage:
        type: "string"

Command line used for generation

https://editor.swagger.io/

Steps to reproduce

Generate Go Client with Swagger generator

Related issues/PRs

https://github.com/swagger-api/swagger-codegen/issues/7751

Suggest a fix/enhancement

When it now comes to decoding the response of the endpoint the generate Golang code looks like:

func (a *AdministrationApiService) AboutVersionGet(ctx context.Context) (string, *http.Response, error) {
	var (
		localVarHttpMethod  = strings.ToUpper("Get")
		localVarPostBody    interface{}
		localVarFileName    string
		localVarFileBytes   []byte
		localVarReturnValue string
	)

	// create path and map variables
	localVarPath := a.client.cfg.BasePath + "/about/version"

	localVarHeaderParams := make(map[string]string)
	localVarQueryParams := url.Values{}
	localVarFormParams := url.Values{}

	// 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{"text/plain"}

	// 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 localVarReturnValue, nil, err
	}

	localVarHttpResponse, err := a.client.callAPI(r)
	if err != nil || localVarHttpResponse == nil {
		return localVarReturnValue, localVarHttpResponse, err
	}

	localVarBody, err := ioutil.ReadAll(localVarHttpResponse.Body)
	localVarHttpResponse.Body.Close()
	if err != nil {
		return localVarReturnValue, localVarHttpResponse, err
	}

	if localVarHttpResponse.StatusCode < 300 {
		// If we succeed, return the data, otherwise pass on to decode error.
                //added by issue author: normal cast form byte to string would be enough if Content-Type is plain-text
		err = a.client.decode(&localVarReturnValue, localVarBody, localVarHttpResponse.Header.Get("Content-Type"))
		return localVarReturnValue, localVarHttpResponse, err
	}

	if localVarHttpResponse.StatusCode >= 300 {
		newErr := GenericSwaggerError{
			body:  localVarBody,
			error: localVarHttpResponse.Status,
		}

		if localVarHttpResponse.StatusCode == 200 { //added by issue author: is this even reachable?
			var v string
			err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type"))
			if err != nil {
				newErr.error = err.Error()
				return localVarReturnValue, localVarHttpResponse, newErr
			}
			newErr.model = v
			return localVarReturnValue, localVarHttpResponse, newErr
		}

		if localVarHttpResponse.StatusCode == 400 {
			var v ErrorMessage
			err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type"))
			if err != nil {
				newErr.error = err.Error()
				return localVarReturnValue, localVarHttpResponse, newErr
			}
			newErr.model = v
			return localVarReturnValue, localVarHttpResponse, newErr
		}

		if localVarHttpResponse.StatusCode == 500 {
			var v ErrorMessage
			err = a.client.decode(&v, localVarBody, localVarHttpResponse.Header.Get("Content-Type"))
			if err != nil {
				newErr.error = err.Error()
				return localVarReturnValue, localVarHttpResponse, newErr
			}
			newErr.model = v
			return localVarReturnValue, localVarHttpResponse, newErr
		}

		return localVarReturnValue, localVarHttpResponse, newErr
	}

	return localVarReturnValue, localVarHttpResponse, nil
}

The problem here is that the decode() function only is able to decode xml or JSON data.
What we need is cast from byte to string if the contenttype is text/plain

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 using the Swagger declaration and generated Go client shown in the report, then trace the generated client's decode() call for the text/plain response. Done means the plain-text response is returned as a string while existing JSON and XML decoding continues to work.

Written by the indexing model from the issue text.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.