我想向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
)
答案 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)