Skip to content

Instantly share code, notes, and snippets.

@larsonmars
Created February 4, 2021 08:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save larsonmars/a33bc9ef83b617798433e695e4643de4 to your computer and use it in GitHub Desktop.
Save larsonmars/a33bc9ef83b617798433e695e4643de4 to your computer and use it in GitHub Desktop.
HTTP Post into File Writing Service
#!/usr/bin/env python3
from http.server import BaseHTTPRequestHandler, HTTPServer
import logging
import os
from datetime import datetime
class PostRequestWritingServer(HTTPServer):
_counter = 0
class FileWritingPostRequestHandler(BaseHTTPRequestHandler):
def _set_response(self):
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
def do_POST(self):
timestamp = datetime.utcnow()
content_length = int(self.headers['Content-Length'])
content = self.rfile.read(content_length).decode('utf-8')
ip = self.headers['X-Forwarded-For']
agent=self.headers['User-Agent']
logging.info("Received %d bytes from %s (%s) %s", content_length, ip, agent, timestamp)
timestamp_string = timestamp.strftime('%Y-%m-%dT%H:%M:%S,%f%z')
dump = f"Time: {timestamp_string}\nIP: {ip}\nUser-Agent: {agent}\nContent:\n{content}"
filepath = self.server._out_dir_path
filename_time_string = timestamp.strftime('%Y%m%d%H%M%S%f')
filename = f"post_{filename_time_string}_{self.server._counter}.txt"
self.server._counter += 1
out_path = os.path.join(filepath, filename)
with open(out_path, 'w') as file:
file.write(dump)
self._set_response()
def __init__(self, server_address, out_dir_path):
self._out_dir_path = out_dir_path
super().__init__(server_address, self.FileWritingPostRequestHandler);
def run(port=8080, outdir='.'):
logging.basicConfig(format='%(asctime)s %(levelname)s: %(message)s', level=logging.INFO)
server_address = ('', port)
server = PostRequestWritingServer(server_address, outdir)
logging.info("Starting server on port %d...\n", port)
try:
server.serve_forever()
except KeyboardInterrupt:
pass
server.server_close()
logging.info("Stopping server...\n")
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser(description="HTTP Server that dumps POST requests")
parser.add_argument('-p', '--port', type = int, default=8080, help = "The port to listen to (default: 8080)")
parser.add_argument('-o', '--out', help = "The output directory to write to (default: current directory)")
args = parser.parse_args()
run(port=args.port, outdir=args.out)
[Unit]
Description=Post Request Writer Service
After=network.target
[Service]
Type=simple
User=http
Group=http
ExecStart=/usr/local/bin/post-request-writer.py -p 7800 -o /srv/http/posts
[Install]
WantedBy=multi-user.target
@larsonmars
Copy link
Author

This service writes every post request into a file. Useful for, e.g., surveys or other user data you would like to collect. You need to set X-Forwarded-For header property to get the IP address of the sender. In NGINX, you could configure it in this way:

location /my-survey/post {
    proxy_pass http://localhost:7800/;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment