在BaseHTTPRequestHandler中填充并返回列表

问题描述 投票:0回答:1

我无法在 BaseHTTPRequestHandler 类中返回列表。 这是我的代码和注释 想法是将传入的带有 json 的 post 请求转发到另一个函数,通过填充新列表/字典来处理它并返回它。 我也无法理解,这样的对象是否根本无法通过requests.post返回

from http.server import BaseHTTPRequestHandler, HTTPServer  
import os  
import time
import threading    
import requests
import json
import calendar

    def calculate(Event_dictionary_list, cached_timestamp):
        Event_dictionary_list.clear() #- empty Event_dictionary_list
        cached_timestamp = 0   
    def Async_func(Event_dictionary_list, cached_timestamp):
        calculate(Event_dictionary_list, cached_timestamp)            
    def handler(event, Event_dictionary_list, cached_timestamp):
        if not Event_dictionary_list: #Checking if Event_dictionary_list is empty 
            cached_timestamp = event['time']
            threading.Timer(60,Async_func, [Event_dictionary_list, cached_timestamp]).start()
            # make decision as to when to calculate
        if event['time'] - cached_timestamp < 60*1000: #- in milliseconds
            Event_dictionary_list.append(event)
    
    class server(BaseHTTPRequestHandler):
        
        def __init__(self, *args, **kwargs):
            self.Event_dictionary_list = []
            self.cached_timestamp = 0
            super().__init__(*args, **kwargs)
                
        def do_POST(self):
            print("post msg received");
            self.data_string = self.rfile.read(int(self.headers['Content-Length']))
            self.event_time = calendar.timegm(time.gmtime())
            self.send_response(200) # 200 = success - thanks for message response
            self.send_header("Content-type", "application/json")
            self.end_headers()
            data = json.loads(self.data_string)
            data['time'] = self.event_time
            # we assume json will be decoded as object, eg:
            if type(data) is dict:
                    handler(data, self.Event_dictionary_list, self.cached_timestamp)
            #Trying to return object, but no luck
            return self.Event_dictionary_list 
            
    def run():
        print('http server is starting...')
        port = 8000
        server_address = ('localhost', port)  
        httpd = HTTPServer(server_address, server)  
        print('http server is listening on port %d' % port)  
        httpd.serve_forever()    
    if __name__ == '__main__':  
      run()

我的要求是这样的:

requests.post(url = 'http://localhost:8000', json = {'key': 'value'})
python-3.x server python-requests http-post basehttprequesthandler
1个回答
0
投票

首先:您需要返回一些字符串数据 - 不是 Python 对象,例如列表、字典等。您可以将 Python 对象编码为 Json 字符串,然后发送该字符串。

第二:我建议对 HTTPServer 进行子类化并将“持久”数据放在那里。

示例:

import json
from http.server import BaseHTTPRequestHandler, HTTPServer


class MyServer(HTTPServer):
    def __init__(self, *args, **kwargs):
        HTTPServer.__init__(self, *args, **kwargs)
        self.my_list = []


class MyCustomHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        # read the data in chunks:
        max_chunk_size = 10 * 1024 * 1024
        size_remaining = int(self.headers["content-length"])
        L = []
        while size_remaining:
            chunk_size = min(size_remaining, max_chunk_size)
            chunk = self.rfile.read(chunk_size)

            if not chunk:
                break

            L.append(chunk)
            size_remaining -= len(L[-1])

        try:
            data = json.loads(b"".join(L).decode("utf-8"))
        except:
            self.send_response(500)
            self.send_header("Content-length", "0")
            self.end_headers()
        else:
            self.server.my_list.append(data)

            response = json.dumps(self.server.my_list, indent=4).encode("utf-8")

            self.send_response(200)
            self.send_header("Content-type", "application/json")

            self.send_header("Content-length", str(len(response)))
            self.end_headers()
            self.wfile.write(response)


def run():
    print("http server is starting...")
    httpd = MyServer(("localhost", 8000), MyCustomHandler)
    print("http server is listening on port %d" % port)
    httpd.serve_forever()


if __name__ == "__main__":
    run()

运行代码会在

localhost:8000
上启动侦听服务器。

然后在其他终端你可以这样做:

$ curl -X POST -H "Content-Type: application/json" -d '{"key": "value"}' http://localhost:8000

[
    {
        "key": "value"
    }
]

执行后续的curl命令将添加到服务器端的列表中并返回它。

© www.soinside.com 2019 - 2024. All rights reserved.