Python http server get post body

1 Answer

You can access POST body in do_POST method like this:

for python 2

content_len = int(self.headers.getheader('content-length', 0))

for python 3

content_len = int(self.headers.get('Content-Length'))

and then read the data

post_body = self.rfile.read(content_len)

Python http server get post body

Brown Bear

18.7k10 gold badges50 silver badges71 bronze badges

answered May 12, 2011 at 10:52

Roman BodnarchukRoman Bodnarchuk

28.5k12 gold badges58 silver badges73 bronze badges

7

  • Note that this leads to a TypeError if the content-length header is not set (e.g. by calling curl -X POST http://your-endpoint). So either make sure to catch it or set a default value for the content-length header: content_len = int(self.headers.getheader('content-length', 0))

    Apr 11, 2014 at 12:35

  • in python3: self.headers.get(...)

    Mar 11, 2015 at 3:49

  • Any reason why self.rfile.read() doesn't just read the entire input on its own? Why do we need to specify the number of bytes to read?

    Jun 19, 2016 at 19:53

  • @sevko because otherwise you will start reading the next pipelined request sent by the client.

    Nov 9, 2017 at 21:43

  • This doesn't feel safe. What happens if a malicious client sends a very large 'Content-Length' value? Won't that cause the server to read more data than it should?

    Dec 24, 2021 at 12:32

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters

#!/usr/bin/env python3
"""
Very simple HTTP server in python for logging requests
Usage::
./server.py []
"""
from http.server import BaseHTTPRequestHandler, HTTPServer
import logging
class S(BaseHTTPRequestHandler):
def _set_response(self):
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
def do_GET(self):
logging.info("GET request,\nPath: %s\nHeaders:\n%s\n", str(self.path), str(self.headers))
self._set_response()
self.wfile.write("GET request for {}".format(self.path).encode('utf-8'))
def do_POST(self):
content_length = int(self.headers['Content-Length']) # <--- Gets the size of data
post_data = self.rfile.read(content_length) # <--- Gets the data itself
logging.info("POST request,\nPath: %s\nHeaders:\n%s\n\nBody:\n%s\n",
str(self.path), str(self.headers), post_data.decode('utf-8'))
self._set_response()
self.wfile.write("POST request for {}".format(self.path).encode('utf-8'))
def run(server_class=HTTPServer, handler_class=S, port=8080):
logging.basicConfig(level=logging.INFO)
server_address = ('', port)
httpd = server_class(server_address, handler_class)
logging.info('Starting httpd...\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()