Skip to content

Commit 9e5de7d

Browse files
committed
Merge pull request #1132 from geekerzp/python-configuration
[Python] Add option `verify_ssl` to switch SSL/TLS verification
2 parents 8de9e23 + b3d28f0 commit 9e5de7d

File tree

10 files changed

+180
-240
lines changed

10 files changed

+180
-240
lines changed

modules/swagger-codegen/src/main/resources/python/api.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class {{classname}}(object):
4343
self.api_client = api_client
4444
else:
4545
if not config.api_client:
46-
config.api_client = ApiClient('{{basePath}}')
46+
config.api_client = ApiClient()
4747
self.api_client = config.api_client
4848
{{#operation}}
4949

modules/swagger-codegen/src/main/resources/python/api_client.mustache

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Copyright 2015 SmartBear Software
2020

2121
from __future__ import absolute_import
2222
from . import models
23-
from .rest import RESTClient
23+
from .rest import RESTClientObject
2424
from .rest import ApiException
2525

2626
import os
@@ -71,6 +71,7 @@ class ApiClient(object):
7171
"""
7272
Constructor of the class.
7373
"""
74+
self.rest_client = RESTClientObject()
7475
self.default_headers = {}
7576
if header_name is not None:
7677
self.default_headers[header_name] = header_value
@@ -330,35 +331,35 @@ class ApiClient(object):
330331
Makes the HTTP request using RESTClient.
331332
"""
332333
if method == "GET":
333-
return RESTClient.GET(url,
334-
query_params=query_params,
335-
headers=headers)
334+
return self.rest_client.GET(url,
335+
query_params=query_params,
336+
headers=headers)
336337
elif method == "HEAD":
337-
return RESTClient.HEAD(url,
338-
query_params=query_params,
339-
headers=headers)
338+
return self.rest_client.HEAD(url,
339+
query_params=query_params,
340+
headers=headers)
340341
elif method == "POST":
341-
return RESTClient.POST(url,
342-
query_params=query_params,
343-
headers=headers,
344-
post_params=post_params,
345-
body=body)
342+
return self.rest_client.POST(url,
343+
query_params=query_params,
344+
headers=headers,
345+
post_params=post_params,
346+
body=body)
346347
elif method == "PUT":
347-
return RESTClient.PUT(url,
348-
query_params=query_params,
349-
headers=headers,
350-
post_params=post_params,
351-
body=body)
348+
return self.rest_client.PUT(url,
349+
query_params=query_params,
350+
headers=headers,
351+
post_params=post_params,
352+
body=body)
352353
elif method == "PATCH":
353-
return RESTClient.PATCH(url,
354-
query_params=query_params,
355-
headers=headers,
356-
post_params=post_params,
357-
body=body)
354+
return self.rest_client.PATCH(url,
355+
query_params=query_params,
356+
headers=headers,
357+
post_params=post_params,
358+
body=body)
358359
elif method == "DELETE":
359-
return RESTClient.DELETE(url,
360-
query_params=query_params,
361-
headers=headers)
360+
return self.rest_client.DELETE(url,
361+
query_params=query_params,
362+
headers=headers)
362363
else:
363364
raise ValueError(
364365
"http method must be `GET`, `HEAD`,"

modules/swagger-codegen/src/main/resources/python/configuration.mustache

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,12 @@ class Configuration(object):
7979
self.__debug = False
8080
self.init_logger()
8181

82+
# SSL/TLS verification
83+
# Set this to false to skip verifying SSL certificate when calling API from https server.
84+
self.verify_ssl = True
85+
# Set this to customize the certificate file to verify the peer.
86+
self.ssl_ca_cert = None
87+
8288
def init_logger(self):
8389
"""
8490
Initializes logger settings.

modules/swagger-codegen/src/main/resources/python/rest.mustache

Lines changed: 56 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Copyright 2015 SmartBear Software
1818
Credit: this file (rest.py) is modified based on rest.py in Dropbox Python SDK:
1919
https://www.dropbox.com/developers/core/sdks/python
2020
"""
21+
from __future__ import absolute_import
2122

2223
import sys
2324
import io
@@ -29,6 +30,8 @@ import logging
2930
# python 2 and python 3 compatibility library
3031
from six import iteritems
3132

33+
from .configuration import Configuration
34+
3235
try:
3336
import urllib3
3437
except ImportError:
@@ -69,31 +72,24 @@ class RESTResponse(io.IOBase):
6972
class RESTClientObject(object):
7073

7174
def __init__(self, pools_size=4):
72-
# http pool manager
73-
self.pool_manager = urllib3.PoolManager(
74-
num_pools=pools_size
75-
)
75+
if Configuration().verify_ssl:
76+
cert_reqs = ssl.CERT_REQUIRED
77+
else:
78+
cert_reqs = ssl.CERT_NONE
79+
80+
if Configuration().ssl_ca_cert:
81+
ca_certs = Configuration().ssl_ca_cert
82+
else:
83+
# if not set certificate file, use Mozilla's root certificates.
84+
ca_certs = certifi.where()
7685

7786
# https pool manager
78-
# certificates validated using Mozilla’s root certificates
79-
self.ssl_pool_manager = urllib3.PoolManager(
87+
self.pool_manager = urllib3.PoolManager(
8088
num_pools=pools_size,
81-
cert_reqs=ssl.CERT_REQUIRED,
82-
ca_certs=certifi.where()
89+
cert_reqs=cert_reqs,
90+
ca_certs=ca_certs
8391
)
8492

85-
def agent(self, url):
86-
"""
87-
Use `urllib3.util.parse_url` for backward compatibility.
88-
Return proper pool manager for the http/https schemes.
89-
"""
90-
url = urllib3.util.parse_url(url)
91-
scheme = url.scheme
92-
if scheme == 'https':
93-
return self.ssl_pool_manager
94-
else:
95-
return self.pool_manager
96-
9793
def request(self, method, url, query_params=None, headers=None,
9894
body=None, post_params=None):
9995
"""
@@ -120,32 +116,37 @@ class RESTClientObject(object):
120116
if 'Content-Type' not in headers:
121117
headers['Content-Type'] = 'application/json'
122118

123-
# For `POST`, `PUT`, `PATCH`
124-
if method in ['POST', 'PUT', 'PATCH']:
125-
if query_params:
126-
url += '?' + urlencode(query_params)
127-
if headers['Content-Type'] == 'application/json':
128-
r = self.agent(url).request(method, url,
129-
body=json.dumps(body),
130-
headers=headers)
131-
if headers['Content-Type'] == 'application/x-www-form-urlencoded':
132-
r = self.agent(url).request(method, url,
133-
fields=post_params,
134-
encode_multipart=False,
135-
headers=headers)
136-
if headers['Content-Type'] == 'multipart/form-data':
137-
# must del headers['Content-Type'], or the correct Content-Type
138-
# which generated by urllib3 will be overwritten.
139-
del headers['Content-Type']
140-
r = self.agent(url).request(method, url,
141-
fields=post_params,
142-
encode_multipart=True,
143-
headers=headers)
144-
# For `GET`, `HEAD`, `DELETE`
145-
else:
146-
r = self.agent(url).request(method, url,
147-
fields=query_params,
148-
headers=headers)
119+
try:
120+
# For `POST`, `PUT`, `PATCH`
121+
if method in ['POST', 'PUT', 'PATCH']:
122+
if query_params:
123+
url += '?' + urlencode(query_params)
124+
if headers['Content-Type'] == 'application/json':
125+
r = self.pool_manager.request(method, url,
126+
body=json.dumps(body),
127+
headers=headers)
128+
if headers['Content-Type'] == 'application/x-www-form-urlencoded':
129+
r = self.pool_manager.request(method, url,
130+
fields=post_params,
131+
encode_multipart=False,
132+
headers=headers)
133+
if headers['Content-Type'] == 'multipart/form-data':
134+
# must del headers['Content-Type'], or the correct Content-Type
135+
# which generated by urllib3 will be overwritten.
136+
del headers['Content-Type']
137+
r = self.pool_manager.request(method, url,
138+
fields=post_params,
139+
encode_multipart=True,
140+
headers=headers)
141+
# For `GET`, `HEAD`, `DELETE`
142+
else:
143+
r = self.pool_manager.request(method, url,
144+
fields=query_params,
145+
headers=headers)
146+
except urllib3.exceptions.SSLError as e:
147+
msg = "{0}\n{1}".format(type(e).__name__, str(e))
148+
raise ApiException(status=0, reason=msg)
149+
149150
r = RESTResponse(r)
150151

151152
# In the python 3, the response.data is bytes.
@@ -227,58 +228,20 @@ class ApiException(Exception):
227228
return error_message
228229

229230

230-
class RESTClient(object):
231-
"""
232-
A class with all class methods to perform JSON requests.
233-
"""
234231

235-
IMPL = RESTClientObject()
236232

237-
@classmethod
238-
def request(cls, *n, **kw):
239-
"""
240-
Perform a REST request and parse the response.
241-
"""
242-
return cls.IMPL.request(*n, **kw)
243233

244-
@classmethod
245-
def GET(cls, *n, **kw):
246-
"""
247-
Perform a GET request using `RESTClient.request()`.
248-
"""
249-
return cls.IMPL.GET(*n, **kw)
250234

251-
@classmethod
252-
def HEAD(cls, *n, **kw):
253-
"""
254-
Perform a HEAD request using `RESTClient.request()`.
255-
"""
256-
return cls.IMPL.GET(*n, **kw)
257235

258-
@classmethod
259-
def POST(cls, *n, **kw):
260-
"""
261-
Perform a POST request using `RESTClient.request()`
262-
"""
263-
return cls.IMPL.POST(*n, **kw)
264236

265-
@classmethod
266-
def PUT(cls, *n, **kw):
267-
"""
268-
Perform a PUT request using `RESTClient.request()`
269-
"""
270-
return cls.IMPL.PUT(*n, **kw)
271237

272-
@classmethod
273-
def PATCH(cls, *n, **kw):
274-
"""
275-
Perform a PATCH request using `RESTClient.request()`
276-
"""
277-
return cls.IMPL.PATCH(*n, **kw)
278238

279-
@classmethod
280-
def DELETE(cls, *n, **kw):
281-
"""
282-
Perform a DELETE request using `RESTClient.request()`
283-
"""
284-
return cls.IMPL.DELETE(*n, **kw)
239+
240+
241+
242+
243+
244+
245+
246+
247+

samples/client/petstore/python/swagger_client/api_client.py

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
from __future__ import absolute_import
2222
from . import models
23-
from .rest import RESTClient
23+
from .rest import RESTClientObject
2424
from .rest import ApiException
2525

2626
import os
@@ -71,6 +71,7 @@ def __init__(self, host=Configuration().host,
7171
"""
7272
Constructor of the class.
7373
"""
74+
self.rest_client = RESTClientObject()
7475
self.default_headers = {}
7576
if header_name is not None:
7677
self.default_headers[header_name] = header_value
@@ -330,35 +331,35 @@ def request(self, method, url, query_params=None, headers=None,
330331
Makes the HTTP request using RESTClient.
331332
"""
332333
if method == "GET":
333-
return RESTClient.GET(url,
334-
query_params=query_params,
335-
headers=headers)
334+
return self.rest_client.GET(url,
335+
query_params=query_params,
336+
headers=headers)
336337
elif method == "HEAD":
337-
return RESTClient.HEAD(url,
338-
query_params=query_params,
339-
headers=headers)
338+
return self.rest_client.HEAD(url,
339+
query_params=query_params,
340+
headers=headers)
340341
elif method == "POST":
341-
return RESTClient.POST(url,
342-
query_params=query_params,
343-
headers=headers,
344-
post_params=post_params,
345-
body=body)
342+
return self.rest_client.POST(url,
343+
query_params=query_params,
344+
headers=headers,
345+
post_params=post_params,
346+
body=body)
346347
elif method == "PUT":
347-
return RESTClient.PUT(url,
348-
query_params=query_params,
349-
headers=headers,
350-
post_params=post_params,
351-
body=body)
348+
return self.rest_client.PUT(url,
349+
query_params=query_params,
350+
headers=headers,
351+
post_params=post_params,
352+
body=body)
352353
elif method == "PATCH":
353-
return RESTClient.PATCH(url,
354-
query_params=query_params,
355-
headers=headers,
356-
post_params=post_params,
357-
body=body)
354+
return self.rest_client.PATCH(url,
355+
query_params=query_params,
356+
headers=headers,
357+
post_params=post_params,
358+
body=body)
358359
elif method == "DELETE":
359-
return RESTClient.DELETE(url,
360-
query_params=query_params,
361-
headers=headers)
360+
return self.rest_client.DELETE(url,
361+
query_params=query_params,
362+
headers=headers)
362363
else:
363364
raise ValueError(
364365
"http method must be `GET`, `HEAD`,"

samples/client/petstore/python/swagger_client/apis/pet_api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def __init__(self, api_client=None):
4242
self.api_client = api_client
4343
else:
4444
if not config.api_client:
45-
config.api_client = ApiClient('http://petstore.swagger.io/v2')
45+
config.api_client = ApiClient()
4646
self.api_client = config.api_client
4747

4848
def update_pet(self, **kwargs):

samples/client/petstore/python/swagger_client/apis/store_api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def __init__(self, api_client=None):
4242
self.api_client = api_client
4343
else:
4444
if not config.api_client:
45-
config.api_client = ApiClient('http://petstore.swagger.io/v2')
45+
config.api_client = ApiClient()
4646
self.api_client = config.api_client
4747

4848
def get_inventory(self, **kwargs):

samples/client/petstore/python/swagger_client/apis/user_api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def __init__(self, api_client=None):
4242
self.api_client = api_client
4343
else:
4444
if not config.api_client:
45-
config.api_client = ApiClient('http://petstore.swagger.io/v2')
45+
config.api_client = ApiClient()
4646
self.api_client = config.api_client
4747

4848
def create_user(self, **kwargs):

0 commit comments

Comments
 (0)