71 lines
2.5 KiB
Python
71 lines
2.5 KiB
Python
|
from socketserver import StreamRequestHandler, TCPServer
|
||
|
from src import endpoints
|
||
|
from src import schema
|
||
|
from src import db
|
||
|
import json
|
||
|
|
||
|
|
||
|
class RequestHandler(StreamRequestHandler):
|
||
|
"""
|
||
|
Receieves and processes json input; dispatches input to the
|
||
|
requested endpoint, or responds with error objects.
|
||
|
"""
|
||
|
|
||
|
|
||
|
def reply(self, obj):
|
||
|
self.wfile.write(bytes(json.dumps(obj), "utf8"))
|
||
|
|
||
|
|
||
|
def handle(self):
|
||
|
try:
|
||
|
request = json.loads(str(self.rfile.read(), "utf8"))
|
||
|
endpoint = request.get("method")
|
||
|
|
||
|
if endpoint not in endpoints.endpoints:
|
||
|
return self.reply(schema.error(2, "Invalid endpoint"))
|
||
|
|
||
|
# check to make sure all the arguments for endpoint are provided
|
||
|
elif any([key not in request for key in endpoints.endpoints[endpoint]]):
|
||
|
return self.reply(schema.error(3, "{} requires: {}".format(
|
||
|
endpoint, ", ".join(endpoints.endpoints[endpoint]))))
|
||
|
|
||
|
elif endpoint not in endpoints.authless:
|
||
|
if not request.get("user"):
|
||
|
return self.reply(schema.error(4, "No username provided."))
|
||
|
|
||
|
user = db.user_resolve(request["user"])
|
||
|
request["user"] = user
|
||
|
|
||
|
if not user:
|
||
|
return self.reply(schema.error(5, "User not registered"))
|
||
|
|
||
|
elif endpoint != "check_auth" and not \
|
||
|
db.user_auth(user, request.get("auth_hash")):
|
||
|
return self.reply(schema.error(6, "Authorization failed."))
|
||
|
|
||
|
# post_ids are always returned as integers, but for callers who
|
||
|
# provide them as something else, try to convert them.
|
||
|
if isinstance(request.get("post_id"), (float, str)):
|
||
|
try: request["post_id"] = int(request["post_id"])
|
||
|
except Exception:
|
||
|
return schema.error(3, "Non-numeric post_id")
|
||
|
|
||
|
# exception handling is now passed to the endpoints;
|
||
|
# anything unhandled beyond here is a code 1
|
||
|
self.reply(eval("endpoints." + endpoint)(request))
|
||
|
|
||
|
except json.decoder.JSONDecodeError as E:
|
||
|
return self.reply(schema.error(0, str(E)))
|
||
|
|
||
|
except Exception as E:
|
||
|
return self.reply(schema.error(1, str(E)))
|
||
|
|
||
|
|
||
|
def run(host, port):
|
||
|
server = TCPServer((host, port), RequestHandler)
|
||
|
try:
|
||
|
server.serve_forever()
|
||
|
except KeyboardInterrupt:
|
||
|
print("bye")
|
||
|
server.server_close()
|