如何将POST数据解析成字典
How to parse POST data into a dictionary
我正在尝试编写一个简单的“服务器”,它继承自 BaseHTTPRequestHandler
并且能够接收 GET 和 POST 请求。我有一个 server.py
文件,到目前为止,它看起来像这样:
from http.server import BaseHTTPRequestHandler, HTTPServer
from cgi import parse_header, parse_multipart
from urllib.parse import parse_qs
host = "localhost"
port = 8080
hello_msg = "Server running..."
class Server(BaseHTTPRequestHandler):
def _set_headers(self):
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
def do_GET(self):
self.respond_OK(hello_msg)
def do_POST(self):
print("Post")
data = self.parse_POST()
print(data)
print(type(data))
self.respond_OK("End post")
def parse_POST(self):
ctype, pdict = parse_header(self.headers['content-type'])
if ctype == 'multipart/form-data':
postvars = parse_multipart(self.rfile, pdict)
elif ctype == 'application/x-www-form-urlencoded':
length = int(self.headers['content-length'])
postvars = parse_qs(
self.rfile.read(length),
keep_blank_values=1)
else:
postvars = {}
return postvars
def respond_OK(self, msg):
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
self.wfile.write(bytes(msg, "utf-8"))
if __name__ == "__main__":
webServer = HTTPServer((host, port), Server)
print("Server started http://%s:%s" % (host, port))
try:
webServer.serve_forever()
except KeyboardInterrupt:
pass
webServer.server_close()
print("Server stopped.")
还有一个 client.py
文件,如下所示:
import requests
sample = {
"msg": "sample post message",
"number": 159687,
"list": ["one", "two", "three"]
}
url = "http://localhost:8080"
r = requests.post(url, sample)
在 do_POST
函数中,我希望 data
变量与客户端发送的 sample
变量完全相同,但我最终得到的是这个:
{b'msg': [b'sample post message'], b'number': [b'159687'], b'list': [b'one', b'two', b'three']}
如你所见,它是一个字典,但键和值是字节而不是字符串。我可以在解析它们之后简单地转换键和值,但我的印象是我做错了什么,解析的结果应该已经是字符串而不是字节。
我做错了什么?这里的解决方案是简单地添加另一个将字节转换为字符串的步骤吗?
如果您使用 .decode()
,那么您会得到 strings
而不是 bytes
。
result = parse_qs(data.decode(), strict_parsing=True)
但是您必须自己转换列表。
for key in result:
if len(result[key]) == 1: # if list has only one element
result[key] = result[key][0] # then get it from list
我只使用字典中的 key
(没有 value
)来对原始字典进行更改 result
。
最小工作示例
from urllib.parse import parse_qs
data = b'msg=sample+post+message&number=159687&list=one&list=two&list=three'
data = data.decode()
result = parse_qs(data, strict_parsing=True)
print(result)
for key in result:
if len(result[key]) == 1:
result[key] = result[key][0]
print(result)
我正在尝试编写一个简单的“服务器”,它继承自 BaseHTTPRequestHandler
并且能够接收 GET 和 POST 请求。我有一个 server.py
文件,到目前为止,它看起来像这样:
from http.server import BaseHTTPRequestHandler, HTTPServer
from cgi import parse_header, parse_multipart
from urllib.parse import parse_qs
host = "localhost"
port = 8080
hello_msg = "Server running..."
class Server(BaseHTTPRequestHandler):
def _set_headers(self):
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
def do_GET(self):
self.respond_OK(hello_msg)
def do_POST(self):
print("Post")
data = self.parse_POST()
print(data)
print(type(data))
self.respond_OK("End post")
def parse_POST(self):
ctype, pdict = parse_header(self.headers['content-type'])
if ctype == 'multipart/form-data':
postvars = parse_multipart(self.rfile, pdict)
elif ctype == 'application/x-www-form-urlencoded':
length = int(self.headers['content-length'])
postvars = parse_qs(
self.rfile.read(length),
keep_blank_values=1)
else:
postvars = {}
return postvars
def respond_OK(self, msg):
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
self.wfile.write(bytes(msg, "utf-8"))
if __name__ == "__main__":
webServer = HTTPServer((host, port), Server)
print("Server started http://%s:%s" % (host, port))
try:
webServer.serve_forever()
except KeyboardInterrupt:
pass
webServer.server_close()
print("Server stopped.")
还有一个 client.py
文件,如下所示:
import requests
sample = {
"msg": "sample post message",
"number": 159687,
"list": ["one", "two", "three"]
}
url = "http://localhost:8080"
r = requests.post(url, sample)
在 do_POST
函数中,我希望 data
变量与客户端发送的 sample
变量完全相同,但我最终得到的是这个:
{b'msg': [b'sample post message'], b'number': [b'159687'], b'list': [b'one', b'two', b'three']}
如你所见,它是一个字典,但键和值是字节而不是字符串。我可以在解析它们之后简单地转换键和值,但我的印象是我做错了什么,解析的结果应该已经是字符串而不是字节。
我做错了什么?这里的解决方案是简单地添加另一个将字节转换为字符串的步骤吗?
如果您使用 .decode()
,那么您会得到 strings
而不是 bytes
。
result = parse_qs(data.decode(), strict_parsing=True)
但是您必须自己转换列表。
for key in result:
if len(result[key]) == 1: # if list has only one element
result[key] = result[key][0] # then get it from list
我只使用字典中的 key
(没有 value
)来对原始字典进行更改 result
。
最小工作示例
from urllib.parse import parse_qs
data = b'msg=sample+post+message&number=159687&list=one&list=two&list=three'
data = data.decode()
result = parse_qs(data, strict_parsing=True)
print(result)
for key in result:
if len(result[key]) == 1:
result[key] = result[key][0]
print(result)