Last active
January 24, 2019 18:44
-
-
Save craigderington/fe7e79515a4ec31f65ab079dbe51f8b6 to your computer and use it in GitHub Desktop.
Things API reworked with Responder
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import responder | |
import random | |
import logging | |
import uuid | |
from datetime import datetime | |
from marshmallow import Schema, fields | |
api = responder.API( | |
title="ThingsAPI", | |
version="1.0", | |
openapi="3.0.0", | |
docs_route="/docs" | |
) | |
class StorageEngine(object): | |
""" | |
Local Things Storage | |
:return db | |
""" | |
def get_things(self, limit, marker): | |
return [{'id': str(uuid.uuid4()), 'color': 'orange'}] | |
def add_thing(self, thing): | |
thing['id'] = str(uuid.uuid4()) | |
return thing | |
class StorageError(Exception): | |
""" | |
Exception to handle things database storage errors | |
""" | |
@staticmethod | |
def handle(ex, req, resp, params): | |
description = "Sorry, could not write your thing to the database..." | |
logging.critical('The database can not be reached.') | |
return None | |
class SinkAdapter(object): | |
""" | |
Allow calls to an external web service | |
""" | |
engines = { | |
'ddd': 'https://duckduckgo.com', | |
'yyy': 'https://search.yahoo.com' | |
} | |
def __call__(self, req, resp, engine): | |
url = self.engines[engine] | |
params = {'q': req.get_param('q', True)} | |
result = api.requests.get(url, params=params) | |
resp.status_code = result.status_code | |
resp.content_type = result.headers['content-type'] | |
resp.body = result.text | |
def max_body(limit): | |
""" | |
Check max post body and limit | |
:param limit: | |
:return: req.content | |
""" | |
async def check_body(req, resp, resource, params): | |
length = req.content_length | |
if length is not None and length > limit: | |
msg = ('The size of the request is too large. The body must not ' | |
'exceed {} bytes in length.'.format(str(limit))) | |
raise AssertionError('{}'.format(msg)) | |
return check_body | |
class Thing(object): | |
""" | |
Thing class instance | |
""" | |
def __init__(self, id, color): | |
self.id = id | |
self.color = color | |
class ThingSchema(Schema): | |
""" | |
Thing schema | |
""" | |
id = fields.Integer() | |
color = fields.Str() | |
class ThingsResource(object): | |
""" | |
Things API Resource | |
""" | |
def __init__(self, db): | |
self.db = db | |
self.logger = logging.getLogger('thingsapp.' + __name__) | |
async def on_get(self, req, resp, user_id): | |
marker = req.get_param('marker') or '' | |
limit = req.get_param('limit') or 50 | |
try: | |
things = self.db.get_things(marker, limit) | |
schema = ThingsSchema() | |
except Exception as ex: | |
self.logger.error(ex) | |
resp.context['result'] = schema.dump(things) | |
resp.set_header('Powered-By', 'responder') | |
resp.status_code = api.status_codes.HTTP_200 | |
return resp | |
@api.before_requests(max_body(64 * 1024)) | |
async def on_post(self, req, resp, user_id): | |
try: | |
doc = req.context['doc'] | |
except KeyError as key_err: | |
self.logger.error(key_err) | |
proper_thing = self.db.add_thing(doc) | |
resp.status_code = api.status_codes.HTTP_201 | |
resp.location = '{}/things/{}'.format( | |
user_id, proper_thing['id'] | |
) | |
return resp | |
db = StorageEngine() | |
things = ThingsResource(db) | |
api.add_route('/{user_id}/things', things) | |
if __name__ == '__main__': | |
api.run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment