swagger-api / swagger-codegen

swagger-codegen contains a template-driven engine to generate documentation, API clients and server stubs in different languages by parsing your OpenAPI / Swagger definition.
http://swagger.io
Apache License 2.0
17.01k stars 6.03k forks source link

[python] swagger responses versus API behavior #1796

Open rbpasker opened 8 years ago

rbpasker commented 8 years ago

my swagger.json has:

"responses" : {
    "200" : {},
    "400": {}
}

but the python API ( https://github.com/swagger-api/swagger-codegen/blob/master/modules/swagger-codegen/src/main/resources/python/rest.mustache#L176 ) has:

        if r.status not in range(200, 206):
            raise ApiException(http_resp=r)

which means that when a web service returns a 400, the machinery in the generated client code that converts the JSON response in the body into the swagger-generated response object never happens.

Now maybe the idea is that the caller is supposed to catch ApiException and examine self.status for a 400 error, but then how is the http response body supposed to be converted into the schema specified in the "400" section of the swagger file?

I have also looked at the Java client ( https://github.com/swagger-api/swagger-codegen/blob/master/samples/client/petstore/java/default/src/main/java/io/swagger/client/ApiClient.java#L525 ) and it also doesn't do the right thing with any http-reponse-code outside of a 2xx

some clarification one how exactly the non-200 responses should be handled would be useful.

rbpasker commented 8 years ago

Here's an example where I expect the generated code to look for a '400' http-response-code and convert the payload into the object specified in the schema. instead, it just throws an exception, and doesn't deserialize the payload.

$ python 
>>> from swagger_client import DefaultApi
>>> api = DefaultApi()
>>> api.me_get()
Traceback (most recent call last):
  File "bad400.py", line 4, in <module>
    api.me_get()
  File "/Users/rbp/Projects/jupiter/default/lib/python2.7/site-packages/swagger_client/apis/default_api.py", line 117, in me_get
    callback=params.get('callback'))
  File "/Users/rbp/Projects/jupiter/default/lib/python2.7/site-packages/swagger_client/api_client.py", line 320, in call_api
    response_type, auth_settings, callback)
  File "/Users/rbp/Projects/jupiter/default/lib/python2.7/site-packages/swagger_client/api_client.py", line 147, in __call_api
    post_params=post_params, body=body)
  File "/Users/rbp/Projects/jupiter/default/lib/python2.7/site-packages/swagger_client/api_client.py", line 340, in request
    headers=headers)
  File "/Users/rbp/Projects/jupiter/default/lib/python2.7/site-packages/swagger_client/rest.py", line 184, in GET
    query_params=query_params)
  File "/Users/rbp/Projects/jupiter/default/lib/python2.7/site-packages/swagger_client/rest.py", line 177, in request
    raise ApiException(http_resp=r)
swagger_client.rest.ApiException: (400)
Reason: Bad Request
HTTP response headers: HTTPHeaderDict({'Content-Length': '167', 'X-FB-Trace-ID': 'H7rLn7f2TtE', 'Expires': 'Sat, 01 Jan 2000 00:00:00 GMT', 'Vary': 'Accept-Encoding', 'WWW-Authenticate': 'OAuth "Facebook Platform" "invalid_request" "An active access token must be used to query information about the current user."', 'X-FB-Rev': '2114582', 'Connection': 'keep-alive', 'Pragma': 'no-cache', 'Cache-Control': 'no-store', 'Date': 'Mon, 04 Jan 2016 18:09:32 GMT', 'Facebook-API-Version': 'v2.0', 'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json', 'X-FB-Debug': 'UGKA8PeaClQhh3tWMv+pjpaCAO+Py7dQc5tX9HAfNN1reHdaBjf5v3x8XiVqWnrKSJ9OUlbcQs17uQD3BB/xwg=='})
HTTP response body: {"error":{"message":"An active access token must be used to query information about the current user.","type":"OAuthException","code":2500,"fbtrace_id":"H7rLn7f2TtE"}}

here's the associated swagger file:

{
    "swagger": "2.0",
    "info": {
    "version": "0.0.1",
    "title": "<Bad400 API>"
    },
    "host": "graph.facebook.com/",
    "schemes":[
    "https"],
    "paths": {
    "/me" : { 
        "get" : {
        "description": "gets the graph for a particular user", 
        "produces" : [ "application/json" ],
        "responses" : {
            "400" : {

            "description" : "error",
            "schema" : {
                "type" : "object", 
                "properties":{
                "error" : {
                    "schema" :{
                    "type": "object",
                    "properties": {
                        "error": {
                        "type": "object",
                        "properties": {
                            "message": {
                            "type": "string"
                            },
                            "type": {
                            "type": "string"
                            },
                            "code": {
                            "type": "string"
                            },
                            "fbtrace_id": {
                            "type": "string"
                            }
                        }
                        }
                    }
                    }
                }
                }
            }
            }
        }
        }
    }
    }
}
webron commented 8 years ago

Regardless of the potential issue, that's not a valid definition. Your response schema is malformed.

Should be:

"schema" :{
  "type": "object",
  "properties": {
    "error": {
      "type": "object",
      "properties": {
        "message": {
          "type": "string"
        },
        "type": {
          "type": "string"
        },
        "code": {
          "type": "string"
        },
        "fbtrace_id": {
          "type": "string"
        }
      }
    }
  }
}
rbpasker commented 8 years ago

good catch. fixed

wing328 commented 8 years ago

@rbpasker yes, there's a limitation that the error object defined in the spec is not used in the Python.

Currently, ApiException contains status, reason, body and headers. Are you expecting another field to store the Error object, which is deserialised from the HTTP body of the response?

rbpasker commented 8 years ago

its not just the python codegen. the Java codegen has the same behavior.

jaykwonpark commented 7 years ago

Is it fixed on v2.2.2? It seems the code is still there.

https://github.com/swagger-api/swagger-codegen/blob/master/modules/swagger-codegen/src/main/resources/python/rest.mustache#L196