summaryrefslogtreecommitdiff
path: root/wsgi_server.py
diff options
context:
space:
mode:
authorAleš Smodiš <aless@guru.si>2015-08-24 19:09:41 +0200
committerAleš Smodiš <aless@guru.si>2015-08-24 19:09:41 +0200
commita4f639242f9f6221a486e0e91adeb75ba6096f45 (patch)
treea6d1c1207ccd9829031d527f322ad84d89a2a550 /wsgi_server.py
parent5b4f1e25980ee18a323eba1415ed453b3a910ca3 (diff)
Split the development into daemon and wsgi_server.
Implemented basic infrastructure for daemon (Prolog), and partial support for services in wsgi_server.
Diffstat (limited to 'wsgi_server.py')
-rw-r--r--wsgi_server.py128
1 files changed, 128 insertions, 0 deletions
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)