我已经用C ++为学校项目构建了一个Web服务器。我决定使用Python3和request
为Restful API构建自动化测试。但是,我遇到一个问题,当使用requests
通过HTTPS发送请求时,服务器无法正确解码我的请求正文。
这是通过http:
发出的带有请求的预期响应>>> resp = requests.post("http://127.0.0.1:8080/usager/identification", verify=False, json={"ip": "12.2.2.2", "mac":"FF:11:11:DD:DD:DD", "nom": "test_user1"}) ; resp.content
b'{"identificateur":4139190850,"message":"connection successful"}'
但是通过https,我收到一个“格式错误的请求”,这意味着服务器未在有效负载中找到字段ip
,mac
和nom
:
>>> resp = requests.post("https://127.0.0.1:4433/usager/identification", verify=False, json={"ip": "12.2.2.2", "mac":"FF:11:11:DD:DD:DD", "nom": "test_user1"}) ; resp.content
/usr/lib/python3.7/site-packages/urllib3/connectionpool.py:847: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
InsecureRequestWarning)
b'Malformed request'
奇怪的是,它可以通过HTTPS与curl配合使用
curl -k -X POST https://127.0.0.1:4433/usager/identification --data '{"ip": "12.2.2.2", "mac":"FF:11:11:DD:DD:DD", "nom": "test_user1"}' && echo {"identificateur":4139190850,"message":"connection successful"}
我还尝试在Python中使用data
代替json
,结果相似:
>>> resp = requests.post("https://127.0.0.1:4433/usager/identification", verify=False, data='{"ip": "12.2.2.2", "mac":"FF:11:11:DD:DD:DD", "nom": "test_user1"}') ; resp.content
/usr/lib/python3.7/site-packages/urllib3/connectionpool.py:847: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
InsecureRequestWarning)
b'Malformed request'
在这里,我不知道什么请求在做什么与curl有所不同。我总是可以仅在此测试中使用python代码对curl命令进行硬编码,但这没有任何意义。
感谢您的时间。
编辑: 卷曲并显示详细输出:
{16:34}~/code/tp/inf3995-01/project/server/src/common/test:f341 ✗ ➭ curl -v -k -X POST https://127.0.0.1:4433/usager/identification --data '{"ip": "12.2.2.2", "mac":"FF:11:11:DD:DD:DD", "nom": "test_user1"}' && echo
Note: Unnecessary use of -X or --request, POST is already inferred.
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 4433 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, [no content] (0):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server did not agree to a protocol
* Server certificate:
* subject: C=CA; ST=Quebec; O=Caf�-Bistro �l�vation, Inc.; CN=127.0.0.1
* start date: Nov 8 18:38:05 2018 GMT
* expire date: Nov 8 18:38:05 2019 GMT
* issuer: C=CA; ST=Quebec; L=Montreal; O=Team One, Inc.; OU=Server Dept.
* SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
* TLSv1.3 (OUT), TLS app data, [no content] (0):
> POST /usager/identification HTTP/1.1
> Host: 127.0.0.1:4433
> User-Agent: curl/7.62.0
> Accept: */*
> Content-Length: 66
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 66 out of 66 bytes
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, [no content] (0):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS app data, [no content] (0):
< HTTP/1.1 200 OK
< Connection: Keep-Alive
< Content-Length: 63
<
* Connection #0 to host 127.0.0.1 left intact
{"identificateur":4139190850,"message":"connection successful"}
编辑2:我在服务器和Wireshark上使用gdb收集了更多信息:
在服务器端使用curl
的请求正文:
卷曲请求:
curl -k -X POST https://127.0.0.1:4433/usager/identification --data '{"ip": "12.2.2.2", "mac":"FF:11:11:DD:DD:DD", "nom": "test_user1"}' && echo
服务器端的数据:
(gdb) p body
$29 = "{\"ip\": \"12.2.2.2\", \"mac\":\"FF:11:11:DD:DD:DD\", \"nom\": \"test_user1\"}"
并根据要求:
请求:
>>> headers = {'Connection': 'Keep-Alive', 'Content-Type': 'application/x-www-form-urlencoded'}
>>> data = '{"ip": "12.2.2.2", "mac":"FF:11:11:DD:DD:DD", "nom": "tesr1"}'
>>> response = requests.post("https://127.0.0.1:4433/usager/identification", verify=False, headers=headers, data=data) ; response.text
服务器端主体
(gdb) p body
$31 = "\000{\"ip\": \"12.2.2.2\", \"mac\":\"FF:11:11:DD:DD:DD\", \"nom\": \"tesr1\""
因此,在请求中使用相同的数据会导致数据损坏:将空终止符添加到开头,并删除右括号。