有次在使用Python(使用自帶的urllib2
庫)去調(diào)用一個HTTPS的API時一直報錯error 54, 'Connection reset by peer
; 但是通過postman等工具的時候卻能正常返回結(jié)果:
import urllib2
r = urllib2.urlopen('https://xxxxx')
print r.read()
異常如下:
raise URLError(err)
urllib2.URLError: <urlopen error [Errno 54] Connection reset by peer>
通過查看urllib2
的源碼發(fā)現(xiàn), urllib2
是httplib
模塊的一個更高層的封裝倚喂,httplib
是python中一個相對底層的http請求模塊,httplib
請求流程如下, HTTPConnect()
通過python的socket模塊發(fā)起請求;
(null)
|
| HTTPConnection()
v
Idle
|
| putrequest()
v
Request-started
|
| ( putheader() )* endheaders()
v
Request-sent
|
| response = getresponse()
v
Unread-response [Response-headers-read]
|\____________________
| |
| response.read() | putrequest()
v v
Idle Req-started-unread-response
______/|
/ |
response.read() | | ( putheader() )* endheaders()
v v
Request-started Req-sent-unread-response
|
| response.read()
v
Request-sent
當(dāng)發(fā)起HTTPS請求,socket就變成了SSLSocket
(TLS/SSL wrapper for socket objects, 繼承于socket.socket); 查看官方文檔:
This module uses the OpenSSL library. It is available on all modern Unix systems, Windows, Mac OS X, and probably additional platforms, as long as OpenSSL is installed on that platform.
這個模塊依賴計算機上的openssl庫; 不同版本的openssl可能會導(dǎo)致行為的一些變化;
Note: Some behavior may be platform dependent, since calls are made to the operating system socket APIs. The installed version of OpenSSL may also cause variations in behavior. For example, TLSv1.1 and TLSv1.2 come with openssl version 1.0.1.
OpenSSL 是一個開源的安全套接字層密碼庫产还,囊括主要的密碼算法、常用的密鑰和證書封裝管理功能及SSL協(xié)議;
問題原因: 本地MAC環(huán)境的openssl版本位0.9.8zh, 0.9.8zh版本不支持TLSV1.1 TLSV1.2(出于安全考慮,這次被調(diào)用的HTTPS已經(jīng)不支持TLSV1.1以下的版本了)
$openssl version
OpenSSL 0.9.8zh 14 Jan 2016
解決方法: 升級本地的openssl>=1.0.1