Skip to content

Instantly share code, notes, and snippets.

@nitaku
Last active April 15, 2024 14:22
Show Gist options
  • Star 96 You must be signed in to star a gist
  • Fork 29 You must be signed in to fork a gist
  • Save nitaku/10d0662536f37a087e1b to your computer and use it in GitHub Desktop.
Save nitaku/10d0662536f37a087e1b to your computer and use it in GitHub Desktop.
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 server.py 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 - matteo.abrate@gmail.com"
start on started mountall
stop on shutdown
respawn
respawn limit 99 5
script
exec sudo -u www-data /usr/bin/python /data/examples/python_minimal_http/server.py 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_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
def do_HEAD(self):
self._set_headers()
# GET sends back a Hello world message
def do_GET(self):
self._set_headers()
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':
self.send_response(400)
self.end_headers()
return
# read the message and convert it into a python dictionary
length = int(self.headers.getheader('content-length'))
message = json.loads(self.rfile.read(length))
# add a property to the object, just to mess with data
message['received'] = 'ok'
# send the message back
self._set_headers()
self.wfile.write(json.dumps(message))
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
httpd.serve_forever()
if __name__ == "__main__":
from sys import argv
if len(argv) == 2:
run(port=int(argv[1]))
else:
run()
@gitvipin
Copy link

@saiprasad2210 : You get access to path as self.path inside handler. You can process it as you like. An example is here : https://github.com/gitvipin/sql30/blob/master/sql30/api.py#L45

@alexzanderr
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'))

@janzheng
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'))

@NateFerrero
Copy link

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

@janzheng
Copy link

self.wfile.write(json.dumps({'hello'

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