jasonamyers jasonamyers - 11 months ago 202
Python Question

Python Requests requests.exceptions.SSLError: [Errno 8] _ssl.c:504: EOF occurred in violation of protocol

I'm on Ubuntu 12.10 with OpenSSL 1.0.1c, python 2.7.3, Requests 1.0.3 and 1.0.4 (tried both), and when attempting to connect to the website in the url variable with the following code.

def SendInitialRequest(xmlmessage, redirecturl):
url = 'https://centineltest.cardinalcommerce.com/maps/txns.asp'

payload = 'cmpi_msg=' + ET.tostring(xmlmessage)
headers = {
'Content-Type': 'application/x-www-form-urlencoded',
r = requests.post(url, data=payload, headers=headers, verify=None)
print r.text

It throws the following error:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "clams/libs/centinel/thinclient.py", line 134, in SendInitialRequest
r = requests.post(url, data=payload, headers=headers, verify=None)
File "/home/jasonamyers/.virtualenv/clams/lib/python2.7/site-packages/requests/api.py", line 87, in post
return request('post', url, data=data, **kwargs)
File "/home/jasonamyers/.virtualenv/clams/lib/python2.7/site-packages/requests/api.py", line 44, in request
return session.request(method=method, url=url, **kwargs)
File "/home/jasonamyers/.virtualenv/clams/lib/python2.7/site-packages/requests/sessions.py", line 269, in request
resp = self.send(prep, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies)
File "/home/jasonamyers/.virtualenv/clams/lib/python2.7/site-packages/requests/sessions.py", line 364, in send
r = adapter.send(request, **kwargs)
File "/home/jasonamyers/.virtualenv/clams/lib/python2.7/site-packages/requests/adapters.py", line 163, in send
raise SSLError(e)
requests.exceptions.SSLError: [Errno 8] _ssl.c:504: EOF occurred in violation of protocol

Attempting the connection with openssl returns the following:

$ openssl s_client -connect centineltest.cardinalcommerce.com:443
140019346777760:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:s23_lib.c:177:
no peer certificate available
No client certificate CA names sent
SSL handshake has read 0 bytes and written 226 bytes
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE

If I force it to use tls1 it works (output truncated):

$ openssl s_client -tls1 -connect centineltest.cardinalcommerce.com:443
depth=2 C = US, O = "thawte, Inc.", OU = Certification Services Division, OU
verify error:num=20:unable to get local issuer certificate
verify return:0

I've seen numerous bug reports for this; however, I've not found a way to get around it using the python requests library. Any assistance would be greatly appreciated.

Answer Source

Reposting this here for others from the requests issue page:

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, block=False):
        self.poolmanager = PoolManager(num_pools=connections,

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.