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())