Skip to content

Instantly share code, notes, and snippets.

Last active March 28, 2023 14:00
What would you like to do?
Minimal JSON HTTP server in python

A minimal HTTP server in python. It sends a JSON Hello World for GET requests, and echoes back JSON for POST requests.

python 8009
Starting httpd on port 8009...
curl http://localhost:8009
{"received": "ok", "hello": "world"}
curl --data "{\"this\":\"is a test\"}" --header "Content-Type: application/json" http://localhost:8009
{"this": "is a test", "received": "ok"}

Adapted from this Gist, with the addition of code for reading the request body taken from this article.

Please be careful when using a server like this on production environments, because it lacks many important features (threading to name one). You can consult the python documentation about BaseHTTPServer to learn something useful to improve it.

If you are on Ubuntu, you can install this code as a service with an init script (hopefully, with some modifications that make it actually do something useful). Just modify the include server.conf to suit your needs (possibly renaming it and redirecting output to some log files instead of /dev/null), and copy it into /etc/init/. You can then start/stop/restart the server with the usual service command:

sudo service server start
description "Example JSON HTTP server"
author "nitaku -"
start on started mountall
stop on shutdown
respawn limit 99 5
exec sudo -u www-data /usr/bin/python /data/examples/python_minimal_http/ 8009 >> /dev/null 2>> /dev/null
end script
post-start script
end script
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
import SocketServer
import json
import cgi
class Server(BaseHTTPRequestHandler):
def _set_headers(self):
self.send_header('Content-type', 'application/json')
def do_HEAD(self):
# GET sends back a Hello world message
def do_GET(self):
self.wfile.write(json.dumps({'hello': 'world', 'received': 'ok'}))
# POST echoes the message adding a JSON field
def do_POST(self):
ctype, pdict = cgi.parse_header(self.headers.getheader('content-type'))
# refuse to receive non-json content
if ctype != 'application/json':
# read the message and convert it into a python dictionary
length = int(self.headers.getheader('content-length'))
message = json.loads(
# add a property to the object, just to mess with data
message['received'] = 'ok'
# send the message back
def run(server_class=HTTPServer, handler_class=Server, port=8008):
server_address = ('', port)
httpd = server_class(server_address, handler_class)
print 'Starting httpd on port %d...' % port
if __name__ == "__main__":
from sys import argv
if len(argv) == 2:
Copy link

@mfickett : We also need to convert response to bytes as following. Without it we get error , TypeError: a bytes-like object is required, not 'str'

    def do_GET(self):
        response = json.dumps({'hello': 'world', 'received': 'ok'})
        response = bytes(response, 'utf-8')

Copy link

@saiprasad2210 : You get access to path as self.path inside handler. You can process it as you like. An example is here :

Copy link

in do_GET function:
this line is missing encoding to bytes object

self.wfile.write(json.dumps({'hello': 'world', 'received': 'ok'}))

should be:

self.wfile.write(json.dumps({'hello': 'world', 'received': 'ok'}).encode('utf-8'))

Copy link

janzheng commented Jan 9, 2022

self.wfile.write(json.dumps({'hello': 'world', 'received': 'ok'}).encode('utf-8')) is incorrect — you have to encode the json itself, not the output. So this should actually be:
self.wfile.write(json.dumps({'hello': 'world', 'received': 'ok'}).encode('utf-8'))

Copy link

@janzheng your second example is the same code as your first if I'm seeing correctly

Copy link


somehow I also missed the comment on Mar 24 by Alex. I'm going to excuse myself from this conversation hahah...

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