Я создал веб-сервер на C ++ для школьного проекта.Я решил использовать Python3 и request
для создания автоматизированного тестирования Restful API.Однако у меня возникла проблема, из-за которой мое тело запроса не декодируется должным образом сервером при отправке через HTTPS, с requests
.
, вот ожидаемый ответ с запросами через 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'
Как ни странно, он работает с curl, через HTTPS:
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"}
Я также попытался использовать data
вместо json
в python, с похожими результатами:
>>> 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'
Iне могу понять, какие запросы здесь отличаются от curl.Я всегда мог жестко закодировать команду 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: я собрал больше информации, используя gdb на сервере и Wireshark:
тело запроса, на стороне сервера, используя curl
:
запрос 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\""
Таким образом, использование тех же данных в запросе приводит к повреждению данных: нулевой терминатор добавляется в начало, а закрывающая скобка удаляется.