"""Define all routes for the behavioral experiment server.
Here, all API routes for the experiment server are defined.
Consider splitting into its own package if end up being
a lot of routes.
"""
# Circular import OK here. See https://flask.palletsprojects.com/en/1.1.x/patterns/packages/
# pylint: disable=cyclic-import
from datetime import datetime
import os
from flask import request
from werkzeug.utils import secure_filename
from elephant_vending_machine import APP
from .libraries.experiment_logger import create_experiment_logger
ALLOWED_EXTENSIONS = {'pdf', 'png', 'jpg', 'jpeg', 'gif', 'svg'}
IMAGE_UPLOAD_FOLDER = '/static/img'
[docs]@APP.route('/run-trial', methods=['POST'])
def run_trial():
"""Responds with 'Running {trial_name}' string
All requests sent to this route should have a trial_name in
the query string, otherwise a 400 error will be returned
Returns:
HTTP response 200 with payload 'Running {trial_name}' or
HTTP response 400 with payload 'No trial_name specified'
"""
response = ""
if request.args.get('trial_name') is not None:
trial_name = request.args.get('trial_name')
log_filename = str(datetime.utcnow()) + ' ' + trial_name + '.csv'
exp_logger = create_experiment_logger(log_filename)
exp_logger.info("Experiment %s started", trial_name)
response = 'Running ' + str(trial_name)
else:
response = 'No trial_name specified'
return response
[docs]def allowed_file(filename):
"""Determines whether an uploaded image file has an allowed extension.
Returns:
True if filename includes extension and extension is an allowed extension
False otherwise
"""
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
[docs]@APP.route('/image', methods=['POST'])
def upload_image():
"""Return string indicating result of request
**Example request**:
.. sourcecode::
POST /image HTTP/1.1
Host: 127.0.0.1:5000
Content-Type: multipart/form-data; boundary=--------------------------827430006917349763475527
Accept-Encoding: gzip, deflate, br
Content-Length: 737067
Connection: keep-alive
----------------------------827430006917349763475527
Content-Disposition: form-data; name="file"; filename="elephant.jpeg"
<elephant.jpeg>
----------------------------827430006917349763475527--
**Example response**:
.. sourcecode:: http
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 21
Server: Werkzeug/0.16.1 Python/3.8.1
Date: Thu, 13 Feb 2020 15:35:32 GMT
Success: Image saved.
All requests sent to this route should have an image file
included in the body of the request, otherwise a 400 error
will be returned
:status 201: file saved
:status 400: malformed request
"""
response = ""
response_code = 400
if 'file' not in request.files:
response = "Error with request: No file field in body of request."
else:
file = request.files['file']
if file.filename == '':
response = "Error with request: File field in body of response with no file present."
elif file and allowed_file(file.filename):
filename = secure_filename(file.filename)
save_path = os.path.dirname(os.path.abspath(__file__)) + IMAGE_UPLOAD_FOLDER
file.save(os.path.join(save_path, filename))
response = "Success: Image saved."
response_code = 201
else:
response = "Error with request: File extension not allowed."
return response, response_code
[docs]@APP.route('/log', methods=['GET'])
def log():
"""Returns the specified log file
All requests sent to this route should have a log_name in
the query string, otherwise a 400 error will be returned
Returns:
HTTP response 200 if log file exists, or HTTP response 500
if it does not.
"""
response = ""
if request.args.get('log_name') is not None:
response = 'This would be ' + request.args.get('log_name')
else:
response = 'Error with request.'
return response