Last active
December 1, 2015 13:14
-
-
Save justinfay/ef59bc0e4b2b9b86419f to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| """ | |
| Simple module for microservices. | |
| """ | |
| import configparser | |
| import json | |
| import os | |
| from routes import Mapper | |
| import waitress | |
| import webob | |
| from webob.dec import wsgify | |
| from webob.exc import HTTPNotFound, HTTPCreated, HTTPNoContent | |
| CONFIG_ENV = 'MICRO_SERVICE_CONFIG' | |
| DEFAULT_CONFIG = """ | |
| [server] | |
| host = 127.0.0.1 | |
| port = 9999 | |
| """ | |
| def load_config(): | |
| " Configure a config dict object " | |
| config = configparser.ConfigParser() | |
| config.read_string(DEFAULT_CONFIG) | |
| config_file = os.getenv(CONFIG_ENV) | |
| if config_file: | |
| config.read_file(config_file) | |
| return config | |
| """ | |
| Simple backend representing model layer. | |
| """ | |
| _storage = {} | |
| def retrieve(id=None): | |
| if id is not None: | |
| return _storage[id] | |
| return _storage | |
| def create(object): | |
| id = str(int(max(_storage or [0])) + 1) | |
| _storage[id] = dict(object) | |
| def update(id, object): | |
| for k, v in object.iteritems(): | |
| _storage[id][k] = v | |
| def delete(id): | |
| del _storage[id] | |
| CONTENT_TYPE = 'Content-Type' | |
| APPLICATION_JSON = 'application/json' | |
| GET = 'GET' | |
| POST = 'POST' | |
| PUT = 'PUT' | |
| DELETE = 'DELETE' | |
| def _parse_body(request): | |
| """ | |
| Parse the body from a webob `Request` taking the 'Content-Type' | |
| header into account | |
| """ | |
| if request.headers.get(CONTENT_TYPE) == APPLICATION_JSON: | |
| return json.loads(request.body.decode()) | |
| return request.params | |
| def rest(req, id=None): | |
| " REST(ish) endpoint " | |
| if req.method == GET: | |
| try: | |
| obj = retrieve(id) | |
| except KeyError: | |
| raise HTTPNotFound() | |
| return webob.Response( | |
| json.dumps(dict(obj)), | |
| content_type='application/json') | |
| elif req.method == POST: | |
| create(_parse_body(req)) | |
| raise HTTPCreated | |
| elif req.method == PUT: | |
| try: | |
| update(id, _parse_body(req)) | |
| except KeyError: | |
| raise HTTPNotFound | |
| raise HTTPNoContent | |
| elif req.method == DELETE: | |
| try: | |
| delete(id) | |
| except KeyError: | |
| raise HTTPNotFound | |
| raise HTTPNoContent | |
| routes = Mapper() | |
| routes.connect('/', func=rest) | |
| routes.connect('/{id}', func=rest) | |
| @wsgify | |
| def wsgi_app(req): | |
| " The actual WSGI application. " | |
| result = routes.match(environ=req.environ) | |
| if not result: | |
| raise HTTPNotFound() | |
| func = result.pop('func') | |
| return func(req, **result) | |
| def test(): | |
| " Simple functional test suite. " | |
| import requests | |
| global _storage | |
| _storage = {} | |
| base_url = 'http://localhost:9999/' | |
| req = requests.get(base_url) | |
| assert 200 == req.status_code | |
| assert {} == req.json() | |
| print('Empty storage test passed.') | |
| obj = {'1': '1'} | |
| req = requests.post(base_url, obj) | |
| assert 201 == req.status_code | |
| print('Create object test passed.') | |
| req = requests.get(base_url) | |
| assert 200 == req.status_code | |
| assert {'1': {'1': '1'}} == req.json() | |
| print('Get all test passed.') | |
| req = requests.get(base_url + '1') | |
| assert 200 == req.status_code | |
| assert {'1': '1'} == req.json() | |
| print('Get one test passed.') | |
| req = requests.put(base_url + '1', {'1': '100'}) | |
| assert 204 == req.status_code | |
| req = requests.get(base_url + '1') | |
| assert 200 == req.status_code | |
| assert {'1': '100'} == req.json() | |
| print('Update test passed.') | |
| req = requests.delete(base_url + '1') | |
| assert 204 == req.status_code | |
| req = requests.get(base_url + '1') | |
| assert 404 == req.status_code | |
| req = requests.get(base_url) | |
| assert 200 == req.status_code | |
| assert {} == req.json() | |
| print('Delete test passed.') | |
| _storage = {} | |
| obj = {'foo': 1} | |
| req = requests.post(base_url, json=obj) | |
| assert 201 == req.status_code | |
| print('Create JSON object test passed.') | |
| req = requests.get(base_url + '1') | |
| assert 200 == req.status_code | |
| assert {'foo': 1} == req.json() | |
| print('Get one JSON test passed.') | |
| if __name__ == "__main__": | |
| import sys | |
| if 'test' in sys.argv: | |
| test() | |
| else: | |
| config = load_config() | |
| waitress.serve( | |
| wsgi_app, | |
| host=config['server']['host'], | |
| port=config['server']['port']) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment