【发布时间】:2017-11-10 05:36:38
【问题描述】:
我需要将数据发布到 REST 接口,但是接收主机使用的是自签名证书(这不会改变),所以我需要忽略我收到的明显的证书验证错误。
我的初始脚本如下所示:
from urllib.request import Request, urlopen
from urllib.parse import urlencode
post_url = "https://myserver.mydomain.com:30005/myapipath"
post_payload = { "event": { "Title": "Something, sometime, something, Python"} }
post_headers = {'Content-Type': 'application/xml'}
omi_post = Request(url=post_url, data=post_payload, headers=post_headers)
urlopen(omi_post)
如前所述,这会生成以下堆栈跟踪:
Traceback(最近一次调用最后一次):文件 "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\urllib\request.py", 第 1318 行,在 do_open 中 encode_chunked=req.has_header('Transfer-encoding')) 文件 "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\http\client.py", 第 1239 行,应要求提供 self._send_request(method, url, body, headers, encode_chunked) 文件 "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\http\client.py", 第 1285 行,在 _send_request 中 self.endheaders(body, encode_chunked=encode_chunked) 文件 "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\http\client.py", 第 1234 行,在 endheaders 中 self._send_output(message_body, encode_chunked=encode_chunked) 文件 "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\http\client.py", 第 1026 行,在 _send_output 中 self.send(msg) 文件 "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\http\client.py", 第 964 行,在发送中 self.connect() 文件 "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\http\client.py", 第 1400 行,连接中 server_hostname=server_hostname) 文件 "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\ssl.py", 第 407 行,在 wrap_socket 中 _context=self, _session=session) 文件 "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\ssl.py", 第 814 行,在 init 中 self.do_handshake() 文件 "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\ssl.py", 第 1068 行,在 do_handshake 中 self._sslobj.do_handshake() 文件 "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\ssl.py", 第 689 行,在 do_handshake 中 self._sslobj.do_handshake() ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] 证书验证失败 (_ssl.c:777)
在处理上述异常的过程中,又发生了一个异常:
Traceback(最近一次调用最后一次):文件“send_data.py”,第 16 行,在 urlopen(post_it_already) 文件 "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\urllib\request.py", 第 223 行,在 urlopen 中 return opener.open(url, data, timeout) File "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\urllib\request.py", 第 526 行,打开 response = self._open(req, data) 文件 "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\urllib\request.py", 第 544 行,在 _open '_open', req) 文件 "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\urllib\request.py", 第 504 行,在 _call_chain 结果 = func(*args) 文件 "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\urllib\request.py", 第 1361 行,在 https_open context=self._context, check_hostname=self._check_hostname) 文件 "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\urllib\request.py", 第 1320 行,在 do_open 中 引发 URLError(err) urllib.error.URLError:
所以我找到了另一篇关于添加 SSL 上下文的帖子,我做了如下操作:
from urllib.request import Request, urlopen
from urllib.parse import urlencode
import ssl
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
post_url = "https://myserver.mydomain.com:30005/myapipath"
post_payload = { "event": { "Title": "Something, sometime, something, Python"} }
post_headers = {'Content-Type': 'application/xml'}
post_it_already = Request(url=post_url, data=post_payload, headers=post_headers)
urlopen(post_it_already, context=ctx)
但是,这会生成以下堆栈跟踪(无论我如何挥舞拳头):
Traceback(最近一次调用最后一次):文件“send_data.py”,第 15 行,在 urlopen(post_it_already, context=ctx) 文件 "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\urllib\request.py", 第 223 行,在 urlopen 中 return opener.open(url, data, timeout) File "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\urllib\request.py", 第 526 行,打开 response = self._open(req, data) 文件 "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\urllib\request.py", 第 544 行,在 _open '_open', req) 文件 "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\urllib\request.py", 第 504 行,在 _call_chain 结果 = func(*args) 文件 "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\urllib\request.py", 第 1361 行,在 https_open context=self._context, check_hostname=self._check_hostname) 文件 "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\urllib\request.py", 第 1318 行,在 do_open 中 encode_chunked=req.has_header('Transfer-encoding')) 文件 "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\http\client.py", 第 1239 行,应要求提供 self._send_request(method, url, body, headers, encode_chunked) 文件 "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\http\client.py", 第 1285 行,在 _send_request 中 self.endheaders(body, encode_chunked=encode_chunked) 文件 "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\http\client.py", 第 1234 行,在 endheaders 中 self._send_output(message_body, encode_chunked=encode_chunked) 文件 "C:\Users\myusername\AppData\Local\Programs\Python\Python36\lib\http\client.py", 第 1064 行,在 _send_output + b'\r\n' TypeError: can't concat str to bytes
我不知道为什么它抱怨将字符串与字节对象连接起来。我认为它不喜欢我的字符串类型 URL 和我的数据类型有效负载和标头?但是我不确定下一步该做什么。
或者这是一个典型的案例,有人拿 2 个单独的示例代码并期望它们一起工作,而实际上它们就像花生和泡泡糖一样?
【问题讨论】:
标签: python python-3.x ssl urllib urlopen