Skip to content

Instantly share code, notes, and snippets.

@justinfay
Last active December 1, 2015 13:14
Show Gist options
  • Select an option

  • Save justinfay/ef59bc0e4b2b9b86419f to your computer and use it in GitHub Desktop.

Select an option

Save justinfay/ef59bc0e4b2b9b86419f to your computer and use it in GitHub Desktop.
"""
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