1 contributor
#!/usr/bin/env python3
"""
Very simple HTTP server in python for logging POST and GET requests
Usage::
./server.py [<port>]
"""
from http.server import BaseHTTPRequestHandler, HTTPServer
import logging
import datetime
output="httpserve.log"
count=0
lastPostBody=""
lastPostBody2=""
class S(BaseHTTPRequestHandler):
def log_message(self, format, *args):
# This is to silence a bit the server
return
def _set_response(self):
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
def do_GET(self):
timestamp=datetime.datetime.utcnow().isoformat().split(":")
timestamp=timestamp[0]+timestamp[1]
print(timestamp+" ["+str(count)+"] GET : "+str(self.path))
self._set_response()
aggregContent=""
aggregContent+="<head>\n"
aggregContent+="<title>HTTP Watch</title>\n"
aggregContent+="<style>\n"
aggregContent+="html {font-family: arial, verdana, sans-serif;}\n"
aggregContent+="h1 { font-size:20px; font-weight:bold; padding-left: 4px; }\n"
aggregContent+="h2 { font-size:16px; font-weight:bold; }\n"
aggregContent+="h3 { font-size:14px; font-weight:bold; }\n"
aggregContent+=".header { background-color: #5b7e96; color: #ffffff; padding-top: 2px; padding-bottom: 2px;}\n"
aggregContent+=".pre {font-family: monospace;line-height:100%;font-size: 0.8em;}\n"
aggregContent+="</style>\n"
aggregContent+="<script type=\"text/javascript\"> \n\
setTimeout(function(){ \n\
location = '' \n\
},20000); \n\
</script>\n"
aggregContent+="</head>\n"
aggregContent+="<body>\n"
aggregContent+="<a name=\"top\"></a><div class=\"header\"><h1>HTTP Watch</h1></div>"
aggregContent+="<a href=\"#current\">Latest</a> <a href=\"#previous\">Previous</a><br>"
aggregContent+="<a name=\"current\"></a><a href=\"#top\">⇑</a>Last POST was:\n"+lastPostBody+"\n"
aggregContent+="<a href=\"#top\">⇑</a>"
aggregContent+="<hr>"
aggregContent+="<a name=\"previous\"></a><a href=\"#top\">⇑</a>Previous POST was:\n"+lastPostBody2+"\n"
aggregContent+="<a href=\"#top\">⇑</a>"
aggregContent+="</body>\n"
self.wfile.write("{}".format(aggregContent).encode('utf-8'))
with open(output,"a+") as f:
f.write("["+str(count)+"] GET Request: -------------------------------------------\n")
f.write("["+str(count)+"] Path: "+str(self.path)+"\n")
f.write("["+str(count)+"] HeadersBegin:\n"+str(self.headers)+"\n")
f.write("["+str(count)+"] HeadersEnd: -----\n")
f.write("--------------------------------------------------------\n")
def do_POST(self):
global count
global lastPostBody
global lastPostBody2
timestamp=datetime.datetime.utcnow().isoformat().split(":")
timestamp=timestamp[0]+timestamp[1]
content_length = int(self.headers['Content-Length']) # <--- Gets the size of data
post_data = self.rfile.read(content_length) # <--- Gets the data itself
print(timestamp+" ["+str(count)+"] POST : "+str(self.path))
self._set_response()
self.wfile.write("POST request for {}".format(self.path).encode('utf-8'))
lastPostBody2=lastPostBody
lastPostBody=timestamp+" : "+str(count)+" <br>\n<pre>"+str(self.headers)+"</pre>\n<hr>\n<pre>\n"+post_data.decode('utf-8')+"\n</pre>\n"
#Nice-ing
lastPostBody=lastPostBody.replace("}","}\n").replace(",",",\n")
with open(output,"a+") as f:
f.write("["+str(count)+"] POST Request: "+timestamp+" -------------------------------------------\n")
f.write("["+str(count)+"] Path: "+str(self.path)+"\n")
f.write("["+str(count)+"] HeadersBegin:\n"+str(self.headers)+"\n")
f.write("["+str(count)+"] HeadersEnd: -----\n")
f.write("["+str(count)+"] BodyBegin:\n")
f.write(post_data.decode('utf-8')+"\n")
f.write("["+str(count)+"] BodyEnd:\n")
f.write("--------------------------------------------------------\n")
count+=1
def run(server_class=HTTPServer, handler_class=S, port=8001):
logging.basicConfig(level=logging.INFO)
server_address = ('', port)
httpd = server_class(server_address, handler_class)
logging.info('Starting httpd on port '+str(port)+'...\n')
try:
httpd.serve_forever()
except KeyboardInterrupt:
pass
httpd.server_close()
logging.info('Stopping httpd...\n')
if __name__ == '__main__':
from sys import argv
if len(argv) == 2:
run(port=int(argv[1]))
else:
run()