Last active
January 26, 2018 04:50
-
-
Save jeancochrane/acc776f483b598471c4925d6e097cc1d to your computer and use it in GitHub Desktop.
π A simple database server, for getting and setting from a key-value store.
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
#!/usr/bin/env python3 | |
import unittest | |
import json | |
import io | |
from http.server import HTTPServer, BaseHTTPRequestHandler | |
from urllib.error import HTTPError | |
from urllib.request import urlopen | |
class Handler(BaseHTTPRequestHandler): | |
''' | |
Handle requests! | |
''' | |
# Stash submitted data in a hash map in memory | |
datastore = {} | |
def do_GET(self): | |
''' | |
The handler should respond to two patterns of GET requests: | |
- /get?key=keyname -- return the value stored in the key `keyname` | |
- /set?keyname=value -- store the value `value` under the key `keyname` | |
''' | |
# Get the base command ('get' or 'set') and the params | |
cmd, param = self.path.split('?') | |
# Strip off the leading backslash | |
cmd = cmd[1:] | |
# Set some default response values | |
msg = 'Bad request' | |
status_code = 400 | |
response = None | |
if cmd == 'set': | |
# Set a key/value pair | |
key, val = param.split('=') | |
self.datastore[key] = val | |
status_code = 201 | |
msg = 'SET request receieved for params %s=%s' % (key, val) | |
elif cmd == 'get': | |
# Retreive a key/value pair | |
prefix, key = param.split('=') | |
if prefix == 'key': | |
if self.datastore.get(key): | |
status_code = 200 | |
val = self.datastore[key] | |
output = {key: val} | |
response = json.dumps(output).encode('utf-8') | |
else: | |
status_code = 404 | |
msg = 'Key "%s" not found' % key | |
self.send_response(status_code, message=msg) | |
self.send_header("Content-type", "application/json") | |
self.end_headers() | |
if response: | |
self.wfile.write(response) | |
class TestServer(unittest.TestCase): | |
''' | |
Unit tests for the request handler. | |
To run tests, start by running the server: | |
`python3 dbserver.py` | |
Then open another shell and run the tests: | |
`python3 -m unittest dbserver.py` | |
''' | |
def test_set_key(self): | |
set_key = urlopen('http://127.0.0.1:4000/set?testkey=testval') | |
self.assertEqual(set_key.status, 201) | |
self.assertEqual(set_key.msg, 'SET request receieved for params testkey=testval') | |
def test_set_and_get_key(self): | |
set_key = urlopen('http://127.0.0.1:4000/set?testkey=testval') | |
get_key = urlopen('http://127.0.0.1:4000/get?key=testkey') | |
self.assertEqual(get_key.status, 200) | |
self.assertEqual(get_key.read().decode('utf-8'), '{"testkey": "testval"}') | |
def test_key_doesnt_exist(self): | |
with self.assertRaises(HTTPError): | |
get_key = urlopen('http://127.0.0.1:4000/get?key=badkey') | |
self.assertEqual(get_key.msg, 'Key "badkey" not found') | |
if __name__ == '__main__': | |
# Run a simple server on the loopback interface | |
port = 4000 | |
print('Serving HTTP on 127.0.0.1:%d...' % port) | |
server = HTTPServer(('', port), Handler) | |
server.serve_forever() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment