Skip to content

Commit

Permalink
Merge pull request #392 from sjaensch/add-requests-ssl-support
Browse files Browse the repository at this point in the history
Add support for customizing TLS/SSL verification for requests client
  • Loading branch information
sjaensch committed Oct 19, 2018
2 parents 0ac0a28 + 59ef48f commit 627f6c9
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 7 deletions.
27 changes: 23 additions & 4 deletions bravado/requests_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,20 @@ class RequestsClient(HttpClient):
"""Synchronous HTTP client implementation.
"""

def __init__(self):
def __init__(self, ssl_verify=True, ssl_cert=None):
"""
:param ssl_verify: Set to False to disable SSL certificate validation. Provide the path to a
CA bundle if you need to use a custom one.
:param ssl_cert: Provide a client-side certificate to use. Either a sequence of strings pointing
to the certificate (1) and the private key (2), or a string pointing to the combined certificate
and key.
"""
self.session = requests.Session()
self.authenticator = None
self.ssl_verify = ssl_verify
self.ssl_cert = ssl_cert

@staticmethod
def separate_params(request_params):
def separate_params(self, request_params):
"""Splits the passed in dict of request_params into two buckets.
- sanitized_params are valid kwargs for constructing a
Expand All @@ -113,7 +121,10 @@ def separate_params(request_params):
:returns: tuple(sanitized_params, misc_options)
"""
sanitized_params = request_params.copy()
misc_options = {}
misc_options = {
'ssl_verify': self.ssl_verify,
'ssl_cert': self.ssl_cert,
}

if 'connect_timeout' in sanitized_params:
misc_options['connect_timeout'] = \
Expand Down Expand Up @@ -291,8 +302,16 @@ def result(self, timeout=None):
}

prepared_request = self.session.prepare_request(request)
settings = self.session.merge_environment_settings(
prepared_request.url,
None,
None,
self.misc_options['ssl_verify'],
self.misc_options['ssl_cert'],
)
response = self.session.send(
prepared_request,
timeout=self.build_timeout(timeout),
**settings
)
return response
1 change: 1 addition & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

pygments_style = 'sphinx'

autoclass_content = 'both'

# -- Options for HTML output ---------------------------------------------

Expand Down
21 changes: 21 additions & 0 deletions docs/source/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,27 @@ Config key Type Description
Default: ``False``
========================== =============== ===============================================================

Customizing the HTTP client
~~~~~~~~~~~~~~~~~~~~~~~~~~~

bravado's default HTTP client uses the excellent `requests library <http://www.python-requests.org/>`_ to make HTTP
calls. If you'd like to customize its behavior, create a :class:`bravado.requests_client.RequestsClient` instance
yourself and pass it as ``http_client`` argument to :meth:`.SwaggerClient.from_url` or :meth:`.SwaggerClient.from_spec`.

Currently, you can customize SSL/TLS behavior through the arguments ``ssl_verify`` and ``ssl_cert``. They're identical
to the ``verify`` and ``cert`` options of the requests library; please check
`their documentation <http://www.python-requests.org/en/master/user/advanced/#ssl-cert-verification>`_ for usage
instructions. Note that bravado honors the ``REQUESTS_CA_BUNDLE`` environment variable as well.

Using a different HTTP client
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

You can use other HTTP clients with bravado; the fido client ships with bravado (:class:`bravado.fido_client.FidoClient`).
Currently the fido client doesn't support customizing SSL/TLS behavior.

Another well-supported option is `bravado_asyncio <https://github.com/sjaensch/bravado-asyncio>`_, which requires
Python 3.5+. It supports the same ssl options as the default requests client.

.. _request_configuration:

Per-request Configuration
Expand Down
9 changes: 7 additions & 2 deletions tests/requests_client/RequestsClient/separate_params_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ def test_separate_params():
'connect_timeout': 1,
'timeout': 2
}
sanitized, misc = RequestsClient.separate_params(request_params)
sanitized, misc = RequestsClient().separate_params(request_params)
assert sanitized == {'url': 'http://foo.com'}
assert misc == {'connect_timeout': 1, 'timeout': 2}
assert misc == {
'connect_timeout': 1,
'ssl_cert': None,
'ssl_verify': True,
'timeout': 2,
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@


def test_result_header_values_are_bytes(session, request):
session.merge_environment_settings.return_value = {}
request.headers = {b'X-Foo': b'hi'}
RequestsFutureAdapter(session, request, misc_options={}).result()
RequestsFutureAdapter(session, request, misc_options={'ssl_verify': True, 'ssl_cert': None}).result()

# prepare_request should be called with a request containing correctly
# casted headers (bytestrings should be preserved)
Expand Down

0 comments on commit 627f6c9

Please sign in to comment.