如何将POST数据解析到字典中

Tum*_*uma 4 python post python-3.x basehttprequesthandler server

我正在尝试编写一个简单的“服务器”,它继承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.")
Run Code Online (Sandbox Code Playgroud)

和一个client.py看起来像这样的文件:

import requests

sample = {
    "msg": "sample post message",
    "number": 159687,
    "list": ["one", "two", "three"]
}

url = "http://localhost:8080"

r = requests.post(url, sample)
Run Code Online (Sandbox Code Playgroud)

do_POST函数中,我希望变量与客户端发送的变量data完全相同,但我最终得到的是这样的:sample

{b'msg': [b'sample post message'], b'number': [b'159687'], b'list': [b'one', b'two', b'three']}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,它是一个字典,但键和值是字节而不是字符串。我可以在解析键和值后简单地转换它们,但我觉得我做错了什么,并且解析的结果应该已经是字符串而不是字节。

我究竟做错了什么?这里的解决方案是否只是添加另一个将字节转换为字符串的步骤?

fur*_*ras 6

如果你使用.decode(),那么你会得到strings而不是bytes.

result = parse_qs(data.decode(), strict_parsing=True)
Run Code Online (Sandbox Code Playgroud)

但您必须自行转换列表。

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
Run Code Online (Sandbox Code Playgroud)

我仅使用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)
Run Code Online (Sandbox Code Playgroud)