[BUG][PYTHON] Do not set Content-Type for GET, HEAD or DELETE requests (#9852)

* [BUG][PYTHON] Do not set Content-Type for GET, HEAD or DELETE requests

The Python generator no longer sets a default `Content-Type` of
`application/json` for `GET`, `HEAD` and `DELETE` requests.

Having the `Content-Type` set for these requests was causing issues with
other tools which insist that GET, HEAD and DELETE requests do not have
a Content-Type (as per the OpenAPI 3 specification).

An example of the problem that this commit fixes is when using
[Prism][1] as a [validation proxy][2].

[Prism rejects any GET request that has a Content-Type][3].

Here is [an example of the problem manifesting itself][4].

To validate the fix in this commit:

1. Start with any OpenAPI3 spec e.g. the Petstore example at
https://editor.swagger.io/
2. Generate Python client code for the spec
3. Look at the generated `rest.py` e.g. in the [standard sample in this
repo][5] and see that the `Content-Type` defaults to `application/json`
for all HTTP methods (including `GET`, `HEAD` and `DELETE`), rather than
there being no `Content-Type` for `GET`, `HEAD` and `DELETE`.

Fixes #9831

[1]: https://github.com/stoplightio/prism
[2]: https://meta.stoplight.io/docs/prism/docs/guides/03-validation-proxy.md
[3]: https://github.com/stoplightio/prism/issues/1408#issuecomment-690948020
[4]: https://github.com/agilepathway/gauge-openapi-example/pull/28/checks?check_run_id=2888606052#step:13:18
[5]: 969cea8ce1/samples/openapi3/client/petstore/python/petstore_api/rest.py (L141)

* update samples

* Fix Python DELETE bug introduced in earlier commit

The earlier commit 9dfe1f6 introduced a bug for `DELETE` requests on the
standard Python generator.  This commit fixes that bug and also includes
the updated samples.

Co-authored-by: William Cheng <wing328hk@gmail.com>
This commit is contained in:
John Boyes 2021-07-07 04:04:26 +01:00 committed by GitHub
parent 60c4c88a74
commit 7084a79ede
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 24 additions and 24 deletions

View File

@ -129,15 +129,15 @@ class RESTClientObject(object):
timeout = urllib3.Timeout(
connect=_request_timeout[0], read=_request_timeout[1])
if 'Content-Type' not in headers:
headers['Content-Type'] = 'application/json'
try:
# For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE`
if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']:
# Only set a default Content-Type for POST, PUT, PATCH and OPTIONS requests
if (method != 'DELETE') and ('Content-Type' not in headers):
headers['Content-Type'] = 'application/json'
if query_params:
url += '?' + urlencode(query_params)
if re.search('json', headers['Content-Type'], re.IGNORECASE):
if ('Content-Type' not in headers) or (re.search('json', headers['Content-Type'], re.IGNORECASE)):
request_body = None
if body is not None:
request_body = json.dumps(body)

View File

@ -137,15 +137,15 @@ class RESTClientObject(object):
timeout = urllib3.Timeout(
connect=_request_timeout[0], read=_request_timeout[1])
if 'Content-Type' not in headers:
headers['Content-Type'] = 'application/json'
try:
# For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE`
if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']:
# Only set a default Content-Type for POST, PUT, PATCH and OPTIONS requests
if (method != 'DELETE') and ('Content-Type' not in headers):
headers['Content-Type'] = 'application/json'
if query_params:
url += '?' + urlencode(query_params)
if re.search('json', headers['Content-Type'], re.IGNORECASE):
if ('Content-Type' not in headers) or (re.search('json', headers['Content-Type'], re.IGNORECASE)):
request_body = None
if body is not None:
request_body = json.dumps(body)

View File

@ -137,15 +137,15 @@ class RESTClientObject(object):
timeout = urllib3.Timeout(
connect=_request_timeout[0], read=_request_timeout[1])
if 'Content-Type' not in headers:
headers['Content-Type'] = 'application/json'
try:
# For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE`
if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']:
# Only set a default Content-Type for POST, PUT, PATCH and OPTIONS requests
if (method != 'DELETE') and ('Content-Type' not in headers):
headers['Content-Type'] = 'application/json'
if query_params:
url += '?' + urlencode(query_params)
if re.search('json', headers['Content-Type'], re.IGNORECASE):
if ('Content-Type' not in headers) or (re.search('json', headers['Content-Type'], re.IGNORECASE)):
request_body = None
if body is not None:
request_body = json.dumps(body)

View File

@ -137,15 +137,15 @@ class RESTClientObject(object):
timeout = urllib3.Timeout(
connect=_request_timeout[0], read=_request_timeout[1])
if 'Content-Type' not in headers:
headers['Content-Type'] = 'application/json'
try:
# For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE`
if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']:
# Only set a default Content-Type for POST, PUT, PATCH and OPTIONS requests
if (method != 'DELETE') and ('Content-Type' not in headers):
headers['Content-Type'] = 'application/json'
if query_params:
url += '?' + urlencode(query_params)
if re.search('json', headers['Content-Type'], re.IGNORECASE):
if ('Content-Type' not in headers) or (re.search('json', headers['Content-Type'], re.IGNORECASE)):
request_body = None
if body is not None:
request_body = json.dumps(body)

View File

@ -137,15 +137,15 @@ class RESTClientObject(object):
timeout = urllib3.Timeout(
connect=_request_timeout[0], read=_request_timeout[1])
if 'Content-Type' not in headers:
headers['Content-Type'] = 'application/json'
try:
# For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE`
if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']:
# Only set a default Content-Type for POST, PUT, PATCH and OPTIONS requests
if (method != 'DELETE') and ('Content-Type' not in headers):
headers['Content-Type'] = 'application/json'
if query_params:
url += '?' + urlencode(query_params)
if re.search('json', headers['Content-Type'], re.IGNORECASE):
if ('Content-Type' not in headers) or (re.search('json', headers['Content-Type'], re.IGNORECASE)):
request_body = None
if body is not None:
request_body = json.dumps(body)

View File

@ -137,15 +137,15 @@ class RESTClientObject(object):
timeout = urllib3.Timeout(
connect=_request_timeout[0], read=_request_timeout[1])
if 'Content-Type' not in headers:
headers['Content-Type'] = 'application/json'
try:
# For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE`
if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']:
# Only set a default Content-Type for POST, PUT, PATCH and OPTIONS requests
if (method != 'DELETE') and ('Content-Type' not in headers):
headers['Content-Type'] = 'application/json'
if query_params:
url += '?' + urlencode(query_params)
if re.search('json', headers['Content-Type'], re.IGNORECASE):
if ('Content-Type' not in headers) or (re.search('json', headers['Content-Type'], re.IGNORECASE)):
request_body = None
if body is not None:
request_body = json.dumps(body)