2. Technology Behind The API - sight-hkust/ENGG4930C-ForeSee-mobile GitHub Wiki
ForeSee API is written in Python and designed to be deployed to AWS Lambda using Chalice.
The ENGG4930C-ForeSee-api repository README contains the instructions to get started.
Technology Behind
Lambda is an AWS service that enables you to run serverless code, which means you are responsible for writing the code and AWS is responsible for the execution. In order to use the code written in Lambda as an API, it needs to be connected to the internet using another AWS service API Gateway. The micro-framework Chalice enables you to deploy to Lambda from the command-line and takes care of the API Gateway itself.
The project also uses PyMySQL in order to perform operations on the database.
Structure
app.py
handles all the incoming API requests, (if needed) calls functions fromchalicelib/rds.py
, and returns respective values.chalicelib/rds.py
contains all database related functions.chalicelib/rdsconfig.py
contains the credentials to access the database. (Should be created locally not stored on Github)requirements.txt
contains the record of necessary libraries.
Chalicelib
$ chalice deploy
command only sends app.py
and requiremets.txt
; if you want to send any additional files to Lambda as well, they should be under chalicelib
directory.
GET and POST Requests
The API gets triggered by both GET and POST requests via @app.route(...)
decorator. Below is the decorator with parameters of /login
which is a POST function.
@app.route('/login', methods=['POST'], content_types=['application/json'], cors=True)
On the other hand /get_user_records
which is a GET request can be written as below.
@app.route('/get_user_doctors', methods=['GET'], cors=True)
Query Parameters
GET parameters can be directly accessed from app.current_request.query_params
, but POST parameters need to be parsed with the following helper function.
def parse_post_parameters(raw_data):
i_parsed_data = parse_qs(raw_data)
parsed_data = {}
for key in i_parsed_data:
parsed_data[key] = i_parsed_data[key][0]
return parsed_data
parse_post_parameters()
returns a dictionary of query parameters and their values
RDS
All database operations are handled in chalicelib/rds.py
with the function query_handler
, which takes the query and a tuple of string variables. The function has distinct returns:
- SELECT operator returns a tuple of rows.
- SELECT operator with LIMIT 1 returns a single dictionary.
- INSERT operator returns the
id
of the inserted row.
def query_handler(query, variables=()):
global conn
try:
cur = conn.cursor()
if query.startswith("SELECT"):
cur.execute(query, variables)
if query.endswith("LIMIT 1"):
result = cur.fetchone()
return result
else:
results = cur.fetchall()
return results
else:
cur.execute(query, variables)
conn.commit()
return cur.lastrowid
except InterfaceError as err:
conn = pymysql.connect(rds_host, user=name, passwd=password, db=db_name, connect_timeout=5,
cursorclass=cursors.DictCursor, charset='utf8mb4', autocommit=True)
raise err
except OperationalError as err:
if err.args[0] == 2013:
conn = pymysql.connect(rds_host, user=name, passwd=password, db=db_name, connect_timeout=5,
cursorclass=cursors.DictCursor, charset='utf8mb4', autocommit=True)
raise err
Further References
File Uploads
Currently, there are no file uploads integrated to the API but ideas depending on file uploads have been discussed a lot. The most secure and useful way of uploading a file to the AWS environment is using S3 Buckets with presigned URLs. Below is a list of resources that may be helpful.