使用python请求发送带有未编码数据的http发布请求

时间:2020-03-15 10:59:35

标签: python unicode python-requests

我想向REST api发送一个发布请求,但是我所有的字符都经过unicode编码,例如我想以test的形式发送字符串\u0074\u0065\u0073\u0074。无论我如何尝试,该字符串最终都以\\u0074\\u0065\\u0073\\u0074结尾。我可以轻松地例如在Burp中修改请求,并删除双反斜杠以使其正常工作。

因此发送到Web服务器的原始字节为\x5c\x5c\x75\x30\x30\x37\x34\x5c\x5c\x75\x30\x30\x36\x35\x5c\x5c\x75\x30\x30\x37\x33\x5c\x5c\x75\x30\x30\x37\x34

我想要的是: \x5c\x75\x30\x30\x37\x34\x5c\x75\x30\x30\x36\x35\x5c\x75\x30\x30\x37\x33\x5c\x75\x30\x30\x37\x34

我尝试过的一件事是:

import requests

s = 'test'
data = ''
for c in s:
    data +=  "\\u00"+hex(ord(c))[2:].lower()
print(data)
json =  {"user":data}
res = requests.post('http://127.0.0.1/api/getusers', json=json)
print(res.text)

即使我设置了data = '\x5c\x75\x30\x30\x37\x34\x5c\x75\x30\x30\x36\x35\x5c\x75\x30\x30\x37\x33\x5c\x75\x30\x30\x37\x34'仍会发送双后退(\x5x\x5c

1 个答案:

答案 0 :(得分:1)

对我来说很好。经过https://httpbin.davecheney.com/post,Python 3.7和Requests 2.23.0的测试:

import requests, json

url = r"https://httpbin.davecheney.com/post"

data_raw_str = r"\u0074\u0065\u0073\u0074"

s = 'test'
data = ''
for c in s:
    data += '\\u00' + hex(ord(c))[2:].lower()
    #data += fr"\u{ord(c):04x}" # this works, too

json_dict = {'user': data}
r = requests.post(url, json=json_dict)
print(r)

data_returned = json.loads(r.json()['data'])['user']

print(data_raw_str)
print(data)
print(data_returned)
print(data_raw_str == data == data_returned)
print(requests.__version__)

输出:

<Response [200]>
\u0074\u0065\u0073\u0074
\u0074\u0065\u0073\u0074
\u0074\u0065\u0073\u0074
True
2.23.0

编辑:

根据RFC 8259 - The JavaScript Object Notation (JSON) Data Interchange Format-7.字符串:

所有Unicode字符都可以放在引号内,但必须转义的字符除外:引号,反固相线和控制字符(U + 0000至U + 001F)。

因此反斜杠将始终与JSON中的另一个反斜杠一起转义。

我相信手动删除多余的反斜杠会导致服务器的JSON解码器取消对unicode文字的转义,因此您的字符串会变得很旧test

为什么请求必须为JSON?

如果发出此请求,则不会添加其他反斜杠:

requests.post(url, data=data) # data is a str

如果发出此请求,则将键和值进行utf-8编码,然后进行url编码(将单个反斜杠替换为%5C):

requests.post(url, data=json_dict)