153 lines
4.3 KiB
Python
153 lines
4.3 KiB
Python
from __future__ import print_function
|
|
|
|
import json
|
|
import re
|
|
import sys
|
|
|
|
from pprint import pformat
|
|
from traceback import print_exc
|
|
from wsgiref.simple_server import make_server
|
|
|
|
|
|
class PersonModel(object):
|
|
__people__ = [
|
|
{
|
|
'name': {
|
|
'first': 'Hammy',
|
|
'last': 'Spammy',
|
|
},
|
|
'age': 42,
|
|
'id': 1,
|
|
},
|
|
{
|
|
'name': {
|
|
'first': 'Sampers',
|
|
'last': 'Dancer',
|
|
},
|
|
'age': 38,
|
|
'id': 2
|
|
},
|
|
]
|
|
|
|
def __init__(self):
|
|
self._index()
|
|
|
|
def _index(self):
|
|
self.__people_by_id__ = dict(((p['id'], p) for p in self.__people__))
|
|
|
|
def getall(self):
|
|
return self.__people__
|
|
|
|
def get(self, person_id):
|
|
return self.__people_by_id__[person_id]
|
|
|
|
def add(self, person):
|
|
person['id'] = len(self.__people__) + 1
|
|
self.__people__.append(person)
|
|
self._index()
|
|
return person['id']
|
|
|
|
|
|
class PersonApp(object):
|
|
__routes__ = [
|
|
(_m, _k, re.compile('^{}$'.format(_k)), _v) for _m, _k, _v in (
|
|
('GET', '/people.json', 'all'),
|
|
('POST', '/people.json', 'new'),
|
|
('GET', '/people/(.*)\.json', 'get'),
|
|
('GET', '/', 'echo')
|
|
)
|
|
]
|
|
|
|
def __init__(self):
|
|
self.people = PersonModel()
|
|
print('Routes = {}'.format(pformat(self.__routes__)))
|
|
|
|
def __call__(self, environ, start_response):
|
|
path = '/' + environ.get('PATH_INFO', '').lstrip('/')
|
|
request_method = environ.get('REQUEST_METHOD', 'GET')
|
|
|
|
environ.update({
|
|
'app.path': path,
|
|
'app.request_method': request_method,
|
|
})
|
|
|
|
method_name = 'not_found'
|
|
for route_req_method, route, route_re, route_method in self.__routes__:
|
|
if route_req_method == request_method:
|
|
match = route_re.match(path)
|
|
if match:
|
|
print('Found match: {!r}'.format(match.re.pattern))
|
|
environ['app.route_match'] = match
|
|
method_name = route_method
|
|
break
|
|
|
|
try:
|
|
return getattr(self, method_name)(environ, start_response)
|
|
except AttributeError, exc:
|
|
print_exc()
|
|
return self.not_found(environ, start_response)
|
|
|
|
def not_found(self, environ, start_response):
|
|
print('Nothing matched: {} {!r}'.format(
|
|
environ['app.request_method'], environ['app.path']
|
|
))
|
|
return self._return_json(
|
|
start_response, {'error': 'Not Found'},
|
|
status='404 Not Found'
|
|
)
|
|
|
|
def bad_request(self, environ, start_response):
|
|
return self._return_json(
|
|
start_response, {'error': 'Bad Request'},
|
|
status='400 Bad Request'
|
|
)
|
|
|
|
def get(self, environ, start_response):
|
|
person_id = environ['app.route_match'].group(1)
|
|
if not person_id.isdigit():
|
|
return self.bad_request(environ, start_response)
|
|
|
|
person = self.people.get(int(person_id))
|
|
return self._return_json(start_response, {'person': person})
|
|
|
|
def all(self, environ, start_response):
|
|
return self._return_json(start_response, self.people.getall())
|
|
|
|
def new(self, environ, start_response):
|
|
person = json.loads(
|
|
environ['wsgi.input'].read(int(environ['CONTENT_LENGTH']))
|
|
)
|
|
person_id = self.people.add(person)
|
|
return self._return_json(
|
|
start_response, {}, status='201 Created',
|
|
extra_headers=[
|
|
('location', '/people/{}.json'.format(person_id))
|
|
]
|
|
)
|
|
|
|
def echo(self, environ, start_response):
|
|
return self._return_json(start_response, {'here?': 'yup'})
|
|
|
|
def _return_json(self, start_response, json_dict, status='200 OK',
|
|
extra_headers=()):
|
|
body = json.dumps(json_dict)
|
|
start_response(status, [
|
|
('content-type', 'application/x-json'),
|
|
('content-length', str(len(body)))
|
|
] + list(extra_headers))
|
|
return [body]
|
|
|
|
|
|
def main():
|
|
server = make_server('0.0.0.0', 9282, PersonApp())
|
|
try:
|
|
print('Serving on 0.0.0.0:9282')
|
|
server.serve_forever()
|
|
return 1
|
|
except KeyboardInterrupt:
|
|
return 0
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main())
|