Skip to content

Instantly share code, notes, and snippets.

@mafayaz
Created July 5, 2016 11:57
Show Gist options
  • Save mafayaz/faf938a896357c3a4c9d6da27edcff08 to your computer and use it in GitHub Desktop.
Save mafayaz/faf938a896357c3a4c9d6da27edcff08 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"
@dfrankow
Copy link

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