A Python REST Server

Much of the following code was inspired by (and actually taken from) the book: "Python Cookbook".

The following demonstrates a simple REST server written in Python code. REST stands for "Representational State Transfer."

At the very heart of existing Python Web Frameworks like "Flask" and "Django" you may find the simple logic shown by this working example.

I've slightly modified the code from the book for my example and also created a "template.py" to begin building new servers.

# resty.py (module used by example1.py and template.py)

# modified by Michael Leidel

# from David Beazley & Brian K. Jones

# "Python Cookbook" pp 449-453


import cgi


def notfound_404(environ, start_response):

start_response('404 Not Found', [ ('Content-type', 'text/plain') ])

return [b'Not Found']


class PathDispatcher:

def __init__(self):

self.pathmap = { }


def __call__(self, environ, start_response):

path = environ['PATH_INFO']

params = cgi.FieldStorage(environ['wsgi.input'],

environ=environ)

method = environ['REQUEST_METHOD'].lower()

environ['params'] = { key: params.getvalue(key) for key in params }

handler = self.pathmap.get((method,path), notfound_404)

return handler(environ, start_response)


def register(self, method, path, function):

self.pathmap[method.lower(), path] = function

return function


class safesub(dict):

def __missing__(self, key):

return '{' + key + '}'


# example1.py

# modified from "Python Cookbook"

# by David Beazley & Brian K. Jones

# pp 449-453


import time


_hello_resp = '''\

<html>

<head>

<title>Hello {name}</title>

</head>

<body>

<h1>Hello {name}!</h1>

</body>

</html>'''


def hello_world(environ, start_response):

start_response('200 OK', [ ('Content-type','text/html')])

params = environ['params']

n = params.get('name') # will return 'None' if get fails

resp = _hello_resp.format(name=n)

print ("\nhello_world function firing\n")

yield resp.encode('utf-8')


_localtime_resp = '''\

<?xml version="1.0"?>

<time>

<year>{t.tm_year}</year>

<month>{t.tm_mon}</month>

<day>{t.tm_mday}</day>

<hour>{t.tm_hour}</hour>

<minute>{t.tm_min}</minute>

<second>{t.tm_sec}</second>

</time>'''


def localtime(environ, start_response):

start_response('200 OK', [ ('Content-type', 'application/xml') ])

resp = _localtime_resp.format(t=time.localtime())

print ("\nlocaltime function firing\n")

yield resp.encode('utf-8')


_onemore_resp = '''\

<html>

<head>

<title>onemore</title>

</head>

<body>

<h2>p1 = {p1}</h2>

<h2>p2 = {p2}</h2>

<h2>p3 = {p3}</h2>

</body>

</html>'''


def onemore(environ, start_response):

start_response('200 OK', [ ('Content-type','text/html')])

params = environ['params']

# fill template safely from params

resp = _onemore_resp.format_map(safesub(params))

yield resp.encode('utf-8')


##########################################################


if __name__ == '__main__':

from resty import PathDispatcher

from resty import safesub

from wsgiref.simple_server import make_server


# Create the dispatcher and register functions

dispatcher = PathDispatcher()

dispatcher.register('GET', '/hello', hello_world)

dispatcher.register('GET', '/localtime', localtime)

dispatcher.register('GET', '/onemore', onemore)


# Launch a basic server

httpd = make_server('', 8080, dispatcher)

print('Serving on port 8080...')

httpd.serve_forever()


# template.py

# simple rest template

# Michael Leidel

# inspired by the "Python Cookbook"

# by David Beazley & Brian K. Jones

# pp 449-453


_XXXXXX_resp = '''\

<html>

<head>

<title>Hello {name}</title>

</head>

<body>

<h1>Hello {name}!</h1>

</body>

</html>'''


def XXXXXX(environ, start_response):

start_response('200 OK', [ ('Content-type','text/html')])

params = environ['params']

pvar = params.get('qvar') # will return 'None' if get fails

pvar = params.get('qvar') # will return 'None' if get fails

resp = _XXXXXX_resp.format(svar=pvar)

# print ("\nXXXXXX function firing\n")

yield resp.encode('utf-8')


##########################################################


if __name__ == '__main__':

from resty import PathDispatcher

from resty import safesub

from wsgiref.simple_server import make_server


# Create the dispatcher and register functions

dispatcher = PathDispatcher()

dispatcher.register('GET', '/xxxxxx', XXXXXX)

dispatcher.register('GET', '/xxxxxx', XXXXXX)

dispatcher.register('GET', '/xxxxxx', XXXXXX)


# Launch a basic server

httpd = make_server('', 8080, dispatcher)

print('Serving on port 8080...')

httpd.serve_forever()