From 82e69de44f222f9af0ef0888ae78995298efbd92 Mon Sep 17 00:00:00 2001 From: "chadnickbok@gmail.com" Date: Wed, 14 Mar 2012 15:57:30 -0700 Subject: [PATCH 1/2] Exposed key_file and cert_file in requests, to support https client certificates. --- requests/api.py | 2 ++ requests/models.py | 12 +++++++++++- requests/sessions.py | 12 ++++++++++-- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/requests/api.py b/requests/api.py index b079eedd..3c79646b 100644 --- a/requests/api.py +++ b/requests/api.py @@ -33,6 +33,8 @@ def request(method, url, **kwargs): :param config: (optional) A configuration dictionary. :param verify: (optional) if ``True``, the SSL cert will be verified. A CA_BUNDLE path can also be provided. :param prefetch: (optional) if ``True``, the response content will be immediately downloaded. + :param key_file: (optional) ssl client key file. + :param cert_file: (optional) ssl client cert file. """ s = kwargs.pop('session') if 'session' in kwargs else sessions.session() diff --git a/requests/models.py b/requests/models.py index 753e83ab..d827042b 100644 --- a/requests/models.py +++ b/requests/models.py @@ -63,7 +63,9 @@ class Request(object): config=None, _poolmanager=None, verify=None, - session=None): + session=None, + key_file=None, + cert_file=None): #: Dictionary of configurations for this request. self.config = dict(config or []) @@ -143,6 +145,10 @@ class Request(object): #: SSL Verification. self.verify = verify + #: SSL Certificate + self.key_file = key_file + self.cert_file = cert_file + if headers: headers = CaseInsensitiveDict(self.headers) else: @@ -507,6 +513,10 @@ class Request(object): conn.cert_reqs = 'CERT_NONE' conn.ca_certs = None + if self.key_file and self.cert_file: + conn.key_file = self.key_file + conn.cert_file = self.cert_file + if not self.sent or anyway: if self.cookies: diff --git a/requests/sessions.py b/requests/sessions.py index 04d7d5dd..90fbacf0 100644 --- a/requests/sessions.py +++ b/requests/sessions.py @@ -77,7 +77,9 @@ class Session(object): params=None, config=None, prefetch=False, - verify=True): + verify=True, + key_file=None, + cert_file=None): self.headers = headers or {} self.cookies = cookies or {} @@ -89,6 +91,8 @@ class Session(object): self.config = config or {} self.prefetch = prefetch self.verify = verify + self.key_file = key_file + self.cert_file = cert_file for (k, v) in list(defaults.items()): self.config.setdefault(k, v) @@ -131,7 +135,9 @@ class Session(object): return_response=True, config=None, prefetch=False, - verify=None): + verify=None, + key_file=None, + cert_file=None): """Constructs and sends a :class:`Request `. Returns :class:`Response ` object. @@ -188,6 +194,8 @@ class Session(object): proxies=proxies, config=config, verify=verify, + key_file=key_file, + cert_file=cert_file, _poolmanager=self.poolmanager ) From fc618aa78a63d372e160a42f1589dbb738ab16a2 Mon Sep 17 00:00:00 2001 From: "chadnickbok@gmail.com" Date: Wed, 14 Mar 2012 17:15:29 -0700 Subject: [PATCH 2/2] Updated Requests api to accept a 'cert' argument. This argument can be either a string, containing the path to a pem-formatted key and certificate chain, or a tuple of (cert, key). When supplied a tuple, the values are paths to an SSL certificate chain file and key, respectively. --- requests/api.py | 3 +-- requests/models.py | 18 ++++++++++-------- requests/sessions.py | 15 ++++++--------- 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/requests/api.py b/requests/api.py index 3c79646b..3188a2d0 100644 --- a/requests/api.py +++ b/requests/api.py @@ -33,8 +33,7 @@ def request(method, url, **kwargs): :param config: (optional) A configuration dictionary. :param verify: (optional) if ``True``, the SSL cert will be verified. A CA_BUNDLE path can also be provided. :param prefetch: (optional) if ``True``, the response content will be immediately downloaded. - :param key_file: (optional) ssl client key file. - :param cert_file: (optional) ssl client cert file. + :param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair. """ s = kwargs.pop('session') if 'session' in kwargs else sessions.session() diff --git a/requests/models.py b/requests/models.py index d827042b..717e36fd 100644 --- a/requests/models.py +++ b/requests/models.py @@ -64,8 +64,7 @@ class Request(object): _poolmanager=None, verify=None, session=None, - key_file=None, - cert_file=None): + cert=None): #: Dictionary of configurations for this request. self.config = dict(config or []) @@ -146,8 +145,7 @@ class Request(object): self.verify = verify #: SSL Certificate - self.key_file = key_file - self.cert_file = cert_file + self.cert = cert if headers: headers = CaseInsensitiveDict(self.headers) @@ -273,7 +271,8 @@ class Request(object): _poolmanager=self._poolmanager, proxies=self.proxies, verify=self.verify, - session=self.session + session=self.session, + cert=self.cert ) request.send() @@ -513,9 +512,12 @@ class Request(object): conn.cert_reqs = 'CERT_NONE' conn.ca_certs = None - if self.key_file and self.cert_file: - conn.key_file = self.key_file - conn.cert_file = self.cert_file + if self.cert: + if type(self.cert) is tuple: + conn.cert_file = self.cert[0] + conn.key_file = self.cert[1] + else: + conn.cert_file = self.cert if not self.sent or anyway: diff --git a/requests/sessions.py b/requests/sessions.py index 90fbacf0..61b97490 100644 --- a/requests/sessions.py +++ b/requests/sessions.py @@ -64,7 +64,7 @@ class Session(object): __attrs__ = [ 'headers', 'cookies', 'auth', 'timeout', 'proxies', 'hooks', - 'params', 'config', 'verify'] + 'params', 'config', 'verify', 'cert'] def __init__(self, @@ -78,8 +78,7 @@ class Session(object): config=None, prefetch=False, verify=True, - key_file=None, - cert_file=None): + cert=None): self.headers = headers or {} self.cookies = cookies or {} @@ -91,8 +90,7 @@ class Session(object): self.config = config or {} self.prefetch = prefetch self.verify = verify - self.key_file = key_file - self.cert_file = cert_file + self.cert = cert for (k, v) in list(defaults.items()): self.config.setdefault(k, v) @@ -136,8 +134,7 @@ class Session(object): config=None, prefetch=False, verify=None, - key_file=None, - cert_file=None): + cert=None): """Constructs and sends a :class:`Request `. Returns :class:`Response ` object. @@ -157,6 +154,7 @@ class Session(object): :param config: (optional) A configuration dictionary. :param prefetch: (optional) if ``True``, the response content will be immediately downloaded. :param verify: (optional) if ``True``, the SSL cert will be verified. A CA_BUNDLE path can also be provided. + :param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair. """ method = str(method).upper() @@ -194,8 +192,7 @@ class Session(object): proxies=proxies, config=config, verify=verify, - key_file=key_file, - cert_file=cert_file, + cert=cert, _poolmanager=self.poolmanager )