bbj/src/server.py

79 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
approproate endpoint, or responds with error objects.
"""
def reply(self, dictionary):
self.wfile.write(bytes(json.dumps(dictionary), "utf8"))
def handle(self):
try:
request = json.loads(str(self.rfile.read(), "utf8"))
endpoint = request.get("method")
if endpoint not in endpoints.endpoints:
raise IndexError("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]]):
raise ValueError("{} requires: {}".format(
endpoint, ", ".join(endpoints.endpoints[endpoint])))
elif endpoint not in endpoints.authless:
if not request.get("user"):
raise ConnectionError("No username provided.")
user = db.user_resolve(request["user"])
request["user"] = user
if not user:
raise ConnectionAbortedError("User not registered")
elif endpoint != "check_auth" and not db.user_auth(user, request.get("auth_hash")):
raise ConnectionRefusedError("Authorization failed.")
except json.decoder.JSONDecodeError as E:
return self.reply(schema.error(0, str(E)))
except IndexError as E:
return self.reply(schema.error(2, str(E)))
except ValueError as E:
return self.reply(schema.error(3, str(E)))
except ConnectionError as E:
return self.reply(schema.error(4, str(E)))
except ConnectionAbortedError as E:
return self.reply(schema.error(5, str(E)))
except ConnectionRefusedError as E:
return self.reply(schema.error(6, str(E)))
except Exception as E:
return self.reply(schema.error(1, str(E)))
try:
self.reply(eval("endpoints." + endpoint)(request))
except Exception as E:
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()