I've been using requests in our application for a while; however, recently we've been working on interfacing with payment providers. We've been running into an issue where they use and older firewall/proxy combination that only allows TLSv1, in openssl versions prior to 1 this wasn't a big deal as it would initiate with a TLSv1 request. Beginning in OpenSSL version 1.0 this is no longer the case, and the negotiation process begins with SSL3, this causes these older devices and web servers (older apache) to just throw an EOF or fail the handshake. We need a way to specify an ssl version or negotiation starting point, so we can directly use requests with these older devices. This isn't probably much of a problem for many people; however, I did see a past issues #900, #851, #701, and #606. This isn't a problem on Mac OS X mountain lion unless you install openssl 1.0.1c (security needs), but it's now present by default on Windows and most Linux/Unix variants.
A more through explanation of my problem with code and detailed errors is available at:
http://stackoverflow.com/questions/14102416/python-requests-requests-exceptions-sslerror-errno-8-ssl-c504-eof-occurred
Requests uses shazow/urllib3# for handling this kind of things and you should start with finding out the way to do what you want in urllib3 and then return here and opt for exposing this functionality in Requests.
So urllib3 supports this already by enabled you to specify the SSL_Version when you wrap a socket for example in connectionpool.py:
def connect(self):
# Add certificate verification
sock = socket.create_connection((self.host, self.port), self.timeout)
# Wrap socket using verification with the root certs in
# trusted_root_certs
self.sock = ssl_wrap_socket(sock, self.key_file, self.cert_file,
cert_reqs=self.cert_reqs,
ca_certs=self.ca_certs,
server_hostname=self.host,
ssl_version=self.ssl_version)
to:
def connect(self):
# Add certificate verification
sock = socket.create_connection((self.host, self.port), self.timeout)
# Wrap socket using verification with the root certs in
# trusted_root_certs
self.sock = ssl_wrap_socket(sock, self.key_file, self.cert_file,
cert_reqs=self.cert_reqs,
ca_certs=self.ca_certs,
server_hostname=self.host,
ssl_version=ssl.PROTOCOL_TLSv1)
NOTE: this was supply by Favoretti on the Stack Overflow answer
Requests' does not support doing this before version 1. Subsequent to version 1, you are expected to subclass the HTTPAdapter, like so:
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.poolmanager import PoolManager
import ssl
class MyAdapter(HTTPAdapter):
def init_poolmanager(self, connections, maxsize):
self.poolmanager = PoolManager(num_pools=connections,
maxsize=maxsize,
ssl_version=ssl.PROTOCOL_TLSv1)
When you've done that, you can do this:
import requests
s = requests.Session()
s.mount('https://', MyAdapter())
Any request through that session object will then use TLSv1.
Might have to write up some documentation for doing that. =)
EDIT: Authors note: I have not tried this code, I've only written it in here, so it might not be perfect.
You sir win an internet! Thank you so much!
Glad I could help. =) Thanks for raising an issue!
thanks Lukasa. I forked and patched: https://github.com/serdarakarca/requests
to use:
pip install --upgrade -e git+https://github.com/serdarakarca/requests#egg=requests
@Lukasa I tried the fix which you provided but still i am observing the same issue. Here's the error log
requests.exceptions.SSLError: HTTPSConnectionPool(host='xxxx', port=xxxx): Max retries exceeded with url: /rest/api/content/(Caused by SSLError(SSLError(8, '_ssl.c:504: EOF occurred in violation of protocol'),))
What am I missing here?
PS : I am using windows system where request version is 2.18.4 and Python Version is 2.7.5. I cannot upgrade my Python Version , as there is a constraint.
Most helpful comment
Requests' does not support doing this before version 1. Subsequent to version 1, you are expected to subclass the HTTPAdapter, like so:
When you've done that, you can do this:
Any request through that session object will then use TLSv1.
Might have to write up some documentation for doing that. =)
EDIT: Authors note: I have not tried this code, I've only written it in here, so it might not be perfect.