patternpythonMinor
Simple REST API server
Viewed 0 times
serverrestsimpleapi
Problem
This is a chunk of code I wrote for a job interview at some point - it is a remote key-value storage REST API supporting CRUD operations.
Maybe anyone has some feedback on this? It would be very helpful for me.
I did not attach the tests, since it might be a little bit too much code. You don't have to review both files - even commenting on just one can be extremely helpful.
remotekvs.py
```
# -- test-case-name: tests.remotekvs_test.RemoteKVSTest --
import json
import inspect
from twisted.internet import reactor
from twisted.web.resource import Resource
from twisted.web.server import Site
from keyvaluestorage import KeyValueStorage
class RemoteKVSResource(Resource):
"""
This is a Twisted Resource object used to serve requests for
KeyValueStorage operations. It supports POST, GET, PUT and DELETE
request methods and replies in JSON.
"""
isLeaf = True
def __init__(self):
self.kvs = KeyValueStorage()
def render(self, request):
operations = {
'POST': 'create',
'GET': 'read',
'PUT': 'update',
'DELETE': 'delete'}
if request.method in operations.keys():
response = {
'success': True}
try:
operation = getattr(self.kvs, operations[request.method])
args = {k: v[0] if isinstance(v, list) else v
for k, v in request.args.items()}
result = operation(**(args))
if result is not None:
response['result'] = result
except (TypeError, KeyValueStorage.KeyAlreadyExistsError,
KeyValueStorage.InvalidKeyError), exception:
response['success'] = False
response['error'] = exception.__class__.__name__
if isinstance(exception, TypeError):
response['error_message'] = (
"Valid request parameters: %s." % (
Maybe anyone has some feedback on this? It would be very helpful for me.
I did not attach the tests, since it might be a little bit too much code. You don't have to review both files - even commenting on just one can be extremely helpful.
remotekvs.py
```
# -- test-case-name: tests.remotekvs_test.RemoteKVSTest --
import json
import inspect
from twisted.internet import reactor
from twisted.web.resource import Resource
from twisted.web.server import Site
from keyvaluestorage import KeyValueStorage
class RemoteKVSResource(Resource):
"""
This is a Twisted Resource object used to serve requests for
KeyValueStorage operations. It supports POST, GET, PUT and DELETE
request methods and replies in JSON.
"""
isLeaf = True
def __init__(self):
self.kvs = KeyValueStorage()
def render(self, request):
operations = {
'POST': 'create',
'GET': 'read',
'PUT': 'update',
'DELETE': 'delete'}
if request.method in operations.keys():
response = {
'success': True}
try:
operation = getattr(self.kvs, operations[request.method])
args = {k: v[0] if isinstance(v, list) else v
for k, v in request.args.items()}
result = operation(**(args))
if result is not None:
response['result'] = result
except (TypeError, KeyValueStorage.KeyAlreadyExistsError,
KeyValueStorage.InvalidKeyError), exception:
response['success'] = False
response['error'] = exception.__class__.__name__
if isinstance(exception, TypeError):
response['error_message'] = (
"Valid request parameters: %s." % (
Solution
I'd write the error handling this way:
Note the changes:
In
def render(self, request):
operations = {
'POST': 'create',
'GET': 'read',
'PUT': 'update',
'DELETE': 'delete',
}
if request.method not in operations:
response = {
'success': False,
'error': 'InvalidRequestMethod',
'error_message': ("Valid request methods: %s" % (', '.join(operations.keys()))),
}
request.setResponseCode(http.NOT_ALLOWED)
else:
response = {'success': True}
...
return json.dumps(response)Note the changes:
- Since the error handler is simpler than the main processing code, put it first to get it out of the way.
if request.method not in operationsreads better thanif request.method not in operations.keys()and might be slightly more efficient.
- Reuse
operations.keys()for the error message.
- Set HTTP status 405 ("Method Not Allowed"). (The constant is in
twisted.web.http.)
In
KeyValueStorage, I suggest raising the standard KeyError instead of making your own exception classes.Code Snippets
def render(self, request):
operations = {
'POST': 'create',
'GET': 'read',
'PUT': 'update',
'DELETE': 'delete',
}
if request.method not in operations:
response = {
'success': False,
'error': 'InvalidRequestMethod',
'error_message': ("Valid request methods: %s" % (', '.join(operations.keys()))),
}
request.setResponseCode(http.NOT_ALLOWED)
else:
response = {'success': True}
...
return json.dumps(response)Context
StackExchange Code Review Q#45060, answer score: 2
Revisions (0)
No revisions yet.