Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save isuruf/f9fe7788310c251fcbd51e0d19cc5b71 to your computer and use it in GitHub Desktop.
Save isuruf/f9fe7788310c251fcbd51e0d19cc5b71 to your computer and use it in GitHub Desktop.
Writing Simple HTTP Server in Python (With REST and JSON)
There are many already existing powerful http servers that can be used in python e.g. gevent, twisted web server. However, they are a bit complex to use and you cannot start them in a thread other than the main thread.
Here is a sample of basic http server using "BaseHTTPRequestHandler". The example exposed two rest interfaces:
To ingest records into the web server
To retrieve already ingested records from the web server
The records are assumed to be JSON based, however, any type of records can be ingested.
[sourcecode language="python" wraplines="false" collapse="false"]
from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer
from SocketServer import ThreadingMixIn
import threading
import argparse
import re
import cgi
class LocalData(object):
records = {}
class HTTPRequestHandler(BaseHTTPRequestHandler):
def do_POST(self):
if None != re.search('/api/v1/addrecord/*', self.path):
ctype, pdict = cgi.parse_header(self.headers.getheader('content-type'))
if ctype == 'application/json':
length = int(self.headers.getheader('content-length'))
data = cgi.parse_qs(self.rfile.read(length), keep_blank_values=1)
recordID = self.path.split('/')[-1]
LocalData.records[recordID] = data
print "record %s is added successfully" % recordID
else:
data = {}
self.send_response(200)
self.end_headers()
else:
self.send_response(403)
self.send_header('Content-Type', 'application/json')
self.end_headers()
return
def do_GET(self):
if None != re.search('/api/v1/getrecord/*', self.path):
recordID = self.path.split('/')[-1]
if LocalData.records.has_key(recordID):
self.send_response(200)
self.send_header('Content-Type', 'application/json')
self.end_headers()
self.wfile.write(LocalData.records[recordID])
else:
self.send_response(400, 'Bad Request: record does not exist')
self.send_header('Content-Type', 'application/json')
self.end_headers()
else:
self.send_response(403)
self.send_header('Content-Type', 'application/json')
self.end_headers()
return
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
allow_reuse_address = True
def shutdown(self):
self.socket.close()
HTTPServer.shutdown(self)
class SimpleHttpServer():
def __init__(self, ip, port):
self.server = ThreadedHTTPServer((ip,port), HTTPRequestHandler)
def start(self):
self.server_thread = threading.Thread(target=self.server.serve_forever)
self.server_thread.daemon = True
self.server_thread.start()
def waitForThread(self):
self.server_thread.join()
def addRecord(self, recordID, jsonEncodedRecord):
LocalData.records[recordID] = jsonEncodedRecord
def stop(self):
self.server.shutdown()
self.waitForThread()
if __name__=='__main__':
parser = argparse.ArgumentParser(description='HTTP Server')
parser.add_argument('port', type=int, help='Listening port for HTTP Server')
parser.add_argument('ip', help='HTTP Server IP')
args = parser.parse_args()
server = SimpleHttpServer(args.ip, args.port)
print 'HTTP Server Running...........'
server.start()
server.waitForThread()
[/sourcecode]
Usage:
Copy paste the code above and name it simplewebserver.py
Starting WebServer:
python simplewebserver.py
POST addrecord example using curl:
curl -X POST http://localhost:8080/api/v1/addrecord/1 -d '{\"asif1\":\"test1\"}' -H "Content-Type: application/json"
GET record example using curl:
curl -X GET http://localhost:8080/api/v1/getrecord/test -H "Content-Type: application/json"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment