| ... | ... |
@@ -0,0 +1,110 @@ |
| 1 |
+#!/usr/bin/env python3 |
|
| 2 |
+""" |
|
| 3 |
+Very simple HTTP server in python for logging POST and GET requests |
|
| 4 |
+Usage:: |
|
| 5 |
+ ./server.py [<port>] |
|
| 6 |
+""" |
|
| 7 |
+from http.server import BaseHTTPRequestHandler, HTTPServer |
|
| 8 |
+import logging |
|
| 9 |
+import datetime |
|
| 10 |
+ |
|
| 11 |
+output="httpserve.log" |
|
| 12 |
+count=0 |
|
| 13 |
+lastPostBody="" |
|
| 14 |
+lastPostBody2="" |
|
| 15 |
+ |
|
| 16 |
+class S(BaseHTTPRequestHandler): |
|
| 17 |
+ def log_message(self, format, *args): |
|
| 18 |
+ # This is to silence a bit the server |
|
| 19 |
+ return |
|
| 20 |
+ def _set_response(self): |
|
| 21 |
+ self.send_response(200) |
|
| 22 |
+ self.send_header('Content-type', 'text/html')
|
|
| 23 |
+ self.end_headers() |
|
| 24 |
+ |
|
| 25 |
+ def do_GET(self): |
|
| 26 |
+ timestamp=datetime.datetime.utcnow().isoformat().split(":")
|
|
| 27 |
+ timestamp=timestamp[0]+timestamp[1] |
|
| 28 |
+ print(timestamp+" ["+str(count)+"] GET : "+str(self.path)) |
|
| 29 |
+ self._set_response() |
|
| 30 |
+ aggregContent="" |
|
| 31 |
+ aggregContent+="<head>\n" |
|
| 32 |
+ aggregContent+="<title>HTTP Watch</title>\n" |
|
| 33 |
+ aggregContent+="<style>\n" |
|
| 34 |
+ aggregContent+="html {font-family: arial, verdana, sans-serif;}\n"
|
|
| 35 |
+ aggregContent+="h1 { font-size:20px; font-weight:bold; padding-left: 4px; }\n"
|
|
| 36 |
+ aggregContent+="h2 { font-size:16px; font-weight:bold; }\n"
|
|
| 37 |
+ aggregContent+="h3 { font-size:14px; font-weight:bold; }\n"
|
|
| 38 |
+ aggregContent+=".header { background-color: #5b7e96; color: #ffffff; padding-top: 2px; padding-bottom: 2px;}\n"
|
|
| 39 |
+ aggregContent+=".pre {font-family: monospace;line-height:100%;font-size: 0.8em;}\n"
|
|
| 40 |
+ aggregContent+="</style>\n" |
|
| 41 |
+ aggregContent+="<script type=\"text/javascript\"> \n\ |
|
| 42 |
+ setTimeout(function(){ \n\
|
|
| 43 |
+ location = '' \n\ |
|
| 44 |
+ },20000); \n\ |
|
| 45 |
+ </script>\n" |
|
| 46 |
+ aggregContent+="</head>\n" |
|
| 47 |
+ aggregContent+="<body>\n" |
|
| 48 |
+ aggregContent+="<a name=\"top\"></a><div class=\"header\"><h1>HTTP Watch</h1></div>" |
|
| 49 |
+ aggregContent+="<a href=\"#current\">Latest</a> <a href=\"#previous\">Previous</a><br>" |
|
| 50 |
+ aggregContent+="<a name=\"current\"></a><a href=\"#top\">⇑</a>Last POST was:\n"+lastPostBody+"\n" |
|
| 51 |
+ aggregContent+="<a href=\"#top\">⇑</a>" |
|
| 52 |
+ aggregContent+="<hr>" |
|
| 53 |
+ aggregContent+="<a name=\"previous\"></a><a href=\"#top\">⇑</a>Previous POST was:\n"+lastPostBody2+"\n" |
|
| 54 |
+ aggregContent+="<a href=\"#top\">⇑</a>" |
|
| 55 |
+ aggregContent+="</body>\n" |
|
| 56 |
+ self.wfile.write("{}".format(aggregContent).encode('utf-8'))
|
|
| 57 |
+ with open(output,"a+") as f: |
|
| 58 |
+ f.write("["+str(count)+"] GET Request: -------------------------------------------\n")
|
|
| 59 |
+ f.write("["+str(count)+"] Path: "+str(self.path)+"\n")
|
|
| 60 |
+ f.write("["+str(count)+"] HeadersBegin:\n"+str(self.headers)+"\n")
|
|
| 61 |
+ f.write("["+str(count)+"] HeadersEnd: -----\n")
|
|
| 62 |
+ f.write("--------------------------------------------------------\n")
|
|
| 63 |
+ |
|
| 64 |
+ def do_POST(self): |
|
| 65 |
+ global count |
|
| 66 |
+ global lastPostBody |
|
| 67 |
+ global lastPostBody2 |
|
| 68 |
+ timestamp=datetime.datetime.utcnow().isoformat().split(":")
|
|
| 69 |
+ timestamp=timestamp[0]+timestamp[1] |
|
| 70 |
+ content_length = int(self.headers['Content-Length']) # <--- Gets the size of data |
|
| 71 |
+ post_data = self.rfile.read(content_length) # <--- Gets the data itself |
|
| 72 |
+ print(timestamp+" ["+str(count)+"] POST : "+str(self.path)) |
|
| 73 |
+ |
|
| 74 |
+ self._set_response() |
|
| 75 |
+ self.wfile.write("POST request for {}".format(self.path).encode('utf-8'))
|
|
| 76 |
+ |
|
| 77 |
+ lastPostBody2=lastPostBody |
|
| 78 |
+ lastPostBody=timestamp+" : "+str(count)+" <br>\n<pre>"+str(self.headers)+"</pre>\n<hr>\n<pre>\n"+post_data.decode('utf-8')+"\n</pre>\n"
|
|
| 79 |
+ #Nice-ing |
|
| 80 |
+ lastPostBody=lastPostBody.replace("}","}\n").replace(",",",\n")
|
|
| 81 |
+ with open(output,"a+") as f: |
|
| 82 |
+ f.write("["+str(count)+"] POST Request: "+timestamp+" -------------------------------------------\n")
|
|
| 83 |
+ f.write("["+str(count)+"] Path: "+str(self.path)+"\n")
|
|
| 84 |
+ f.write("["+str(count)+"] HeadersBegin:\n"+str(self.headers)+"\n")
|
|
| 85 |
+ f.write("["+str(count)+"] HeadersEnd: -----\n")
|
|
| 86 |
+ f.write("["+str(count)+"] BodyBegin:\n")
|
|
| 87 |
+ f.write(post_data.decode('utf-8')+"\n")
|
|
| 88 |
+ f.write("["+str(count)+"] BodyEnd:\n")
|
|
| 89 |
+ f.write("--------------------------------------------------------\n")
|
|
| 90 |
+ count+=1 |
|
| 91 |
+ |
|
| 92 |
+def run(server_class=HTTPServer, handler_class=S, port=8001): |
|
| 93 |
+ logging.basicConfig(level=logging.INFO) |
|
| 94 |
+ server_address = ('', port)
|
|
| 95 |
+ httpd = server_class(server_address, handler_class) |
|
| 96 |
+ logging.info('Starting httpd on port '+str(port)+'...\n')
|
|
| 97 |
+ try: |
|
| 98 |
+ httpd.serve_forever() |
|
| 99 |
+ except KeyboardInterrupt: |
|
| 100 |
+ pass |
|
| 101 |
+ httpd.server_close() |
|
| 102 |
+ logging.info('Stopping httpd...\n')
|
|
| 103 |
+ |
|
| 104 |
+if __name__ == '__main__': |
|
| 105 |
+ from sys import argv |
|
| 106 |
+ |
|
| 107 |
+ if len(argv) == 2: |
|
| 108 |
+ run(port=int(argv[1])) |
|
| 109 |
+ else: |
|
| 110 |
+ run() |