From a4f639242f9f6221a486e0e91adeb75ba6096f45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ale=C5=A1=20Smodi=C5=A1?= Date: Mon, 24 Aug 2015 19:09:41 +0200 Subject: Split the development into daemon and wsgi_server. Implemented basic infrastructure for daemon (Prolog), and partial support for services in wsgi_server. --- wsgi_server.py | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 wsgi_server.py (limited to 'wsgi_server.py') diff --git a/wsgi_server.py b/wsgi_server.py new file mode 100644 index 0000000..0f70b40 --- /dev/null +++ b/wsgi_server.py @@ -0,0 +1,128 @@ +#!/usr/bin/python3 +# coding=utf-8 + +import falcon +import json +import client +from errors.session import NoSuchSession, AuthenticationFailed + +MAX_REQUEST_LENGTH = 1024 * 1024 # 1 MB + +api = application = falcon.API() + + +def get_json_payload(req, session_is_optional=False): + if not ((req.content_type == 'application/json') or (req.content_type == 'text/json')): + raise falcon.HTTPUnsupportedMediaType('Unsupported content-type: {0}'.format(req.content_type)) + length = req.get_header('Content-Length') + if length is None: + raise falcon.HTTPLengthRequired('Requests without content-length are not accepted') + try: + l = int(length) + except: + raise falcon.HTTPBadRequest('Invalid Content-Length', 'The given Content-Length is not a number: {0}'.format(length)) + if l > MAX_REQUEST_LENGTH: + raise falcon.HTTPError(falcon.HTTP_413, 'Request Entity Too Large', 'Cannot accept the request of length {0}: maximum allowed content-length is {1}'.format(length, MAX_REQUEST_LENGTH)) + try: + txt = req.stream.read() + except Exception as e: + raise falcon.HTTPBadRequest('Error reading request', 'Error while reading the request body: {0}'.format(e.message)) + try: + js = json.loads(txt, encoding="utf-8") + except ValueError as e: + raise falcon.HTTPBadRequest('Error parsing JSON payload', 'Error while parsing the request as JSON: {0}'.format(e.message)) + sid = js.get('sid') + if sid is None: + if session_is_optional: + return js + raise falcon.HTTPBadRequest('No Session', 'Request is missing a session-ID') + del js['sid'] + try: + session = client.get_session_by_id(sid) + except NoSuchSession: + if session_is_optional: + return js + raise falcon.HTTPBadRequest('Session Expired', 'This user session has expired. Please log-in again.') + req.context['session'] = session + return js + + +class Login(object): + def on_post(self, req, resp): + resp.cache_control = 'private, no-cache, no-store' + js = get_json_payload(req, True) + username = js.get('username') + password = js.get('password') + if username is None: + response = {'code': 1, 'message': 'Username was not provided'} + elif password is None: + response = {'code': 2, 'message': 'Password was not provided'} + else: + try: + session = client.authenticate_and_create_session(username, password) + except AuthenticationFailed: + response = {'code': 3, 'message': 'Username or password do not match'} + else: + response = {'code': 0, 'message': 'OK', 'sid':session.get_sid()} + old_session = req.context.get('session') + if old_session: + old_session.destroy() + resp.body = json.dumps(response) + resp.content_type = 'application/json' + resp.status = falcon.HTTP_200 + +class Activity(object): + def on_get(self, req, resp): + resp.body = '{}' + resp.status = falcon.HTTP_200 + +class Query(object): + def on_post(self, req, resp): + resp.cache_control = 'private, no-cache, no-store' + js = get_json_payload(req) + session = req.context['session'] + step = js.get('step') + if step is None: + response = {'code': 1, 'message': '"step" is not set'} + else: + prolog = session.get_prolog() + if step == 'run': + program = js.get('program') + query = js.get('query') + language = js.get('language') + problem_group = js.get('problem_group') + problem = js.get('problem') + if program is None: + response = {'code': 2, 'message': 'No program specified'} + elif query is None: + response = {'code': 3, 'message': 'No query specified'} + elif language is None: + response = {'code': 4, 'message': 'Language identifier not given'} + elif problem_group is None: + response = {'code': 5, 'message': 'Problem group identifier not given'} + elif problem is None: + response = {'code': 6, 'message': 'Problem identifier not given'} + else: + messages, status, have_more = prolog.run_for_user(session.get_uid(), language, problem_group, problem, program, query) + response = {'code': 0, 'message': 'ok', 'terminal': {'messages': messages, 'status': status, 'have_more': have_more}} + elif step == 'next': + messages, status, have_more = prolog.step() + response = {'code': 0, 'message': 'ok', 'terminal': {'messages': messages, 'status': status, 'have_more': have_more}} + elif step == 'end': + messages, status, have_more = prolog.end() + response = {'code': 0, 'message': 'ok', 'terminal': {'messages': messages, 'status': status, 'have_more': have_more}} + else: + response = {'code': 7, 'message': 'Unknown prolog step: {0}'.format(step)} + + resp.body = json.dumps(response) + resp.content_type = 'application/json' + resp.status = falcon.HTTP_200 + +login = Login() +api.add_route('/login', login) + +activity = Activity() +api.add_route('/activity', activity) + +query = Query() +api.add_route('/query', query) -- cgit v1.2.1