I cannot return list in BaseHTTPRequestHandler class. Here is my code with comments Idea is to forward incoming post request with json to another function, handle it by filling new list/dict and return it. I cannot also understand, whether such object cannot be returned via requests.post at all
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()
My request looks like this:
requests.post(url = 'http://localhost:8000', json = {'key': 'value'})
First: you need to return some string data - not Python object such as list, dict etc. You can encode the python object to Json string for example and send this string.
Second: I recommend to subclass HTTPServer and put the "persistent" data there.
Example:
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()
Running the code starts listening server on localhost:8000
.
Then in other terminal you can do:
$ curl -X POST -H "Content-Type: application/json" -d '{"key": "value"}' http://localhost:8000
[
{
"key": "value"
}
]
Doing subsequent curl commands will add to the list on the server side and return it.