aboutsummaryrefslogtreecommitdiff
path: root/backend
diff options
context:
space:
mode:
authorTerry Truong <terry06890@gmail.com>2022-07-09 03:20:53 +1000
committerTerry Truong <terry06890@gmail.com>2022-07-09 04:36:52 +1000
commit5569c8191ae02f109254282b5943e3ed40032018 (patch)
tree0ec5c2f6176c470aaeaa41be9bfbb0825554b764 /backend
parent347f5127929b17671c75734af5a374ec4f39b5ae (diff)
Replace CGI script with WSGI script and dev server
Diffstat (limited to 'backend')
-rw-r--r--backend/README.md9
-rwxr-xr-xbackend/server.py18
-rwxr-xr-xbackend/tilo.py (renamed from backend/cgi-bin/data.py)67
3 files changed, 53 insertions, 41 deletions
diff --git a/backend/README.md b/backend/README.md
index 3a56f76..358ed72 100644
--- a/backend/README.md
+++ b/backend/README.md
@@ -1,8 +1,9 @@
# Files
-- cgi-bin/data.py: CGI script for providing tree-of-life data to client
+- server.py: Basic dev server that serves a WSGI script
+- tilo.py: WSGI script that serves tree-of-life data
- data: Contains scripts for generating the tree-of-life database
# During development
-Having generated the database as data/data.db, running `python3 -m http.server --cgi 8000`,
-in this directory, allows the client to access the CGI script, and hence the database,
-via `localhost:8000/cgi-bin/data.py`.
+Having generated the database as data/data.db, running `server.py`,
+in this directory, allows the client to access data from `tilo.py`,
+via `localhost:8000`.
diff --git a/backend/server.py b/backend/server.py
new file mode 100755
index 0000000..a00ab7f
--- /dev/null
+++ b/backend/server.py
@@ -0,0 +1,18 @@
+#!/usr/bin/python3
+
+import sys
+from wsgiref.simple_server import make_server
+from tilo import application
+
+usageInfo = f"""
+Usage: {sys.argv[0]}
+
+Runs a basic dev server that serves a WSGI script
+"""
+if len(sys.argv) > 1:
+ print(usageInfo, file=sys.stderr)
+ sys.exit(1)
+
+with make_server('', 8000, application) as httpd:
+ print("Serving HTTP on port 8000...")
+ httpd.serve_forever()
diff --git a/backend/cgi-bin/data.py b/backend/tilo.py
index c1ea181..2f49baa 100755
--- a/backend/cgi-bin/data.py
+++ b/backend/tilo.py
@@ -13,9 +13,9 @@ ROOT_NAME = "cellular organisms"
usageInfo = f"""
Usage: {sys.argv[0]}
-CGI script that provides tree-of-life data, in JSON form.
+WSGI script that serves tree-of-life data, in JSON form.
-Query parameters:
+Expected HTTP query parameters:
- name: Provides a name, or partial name, of a tree-of-life node. If absent, the root node is used.
- type: Specifies what data to reply with.
If 'node', reply with a name-to-TolNode map, describing the named node and it's children.
@@ -219,22 +219,12 @@ def lookupInfo(name, tree, dbCur):
) if n != None else None for n in [name] + subNames
]
return InfoResponse(nodeInfoObjs[0], nodeInfoObjs[1:])
+def getTableSuffix(tree):
+ return "t" if tree == "trimmed" else "i" if tree == "images" else "p"
-# For handling request
-def respondJson(val):
- content = jsonpickle.encode(val, unpicklable=False).encode("utf-8")
- print("Content-type: application/json")
- if "HTTP_ACCEPT_ENCODING" in os.environ and "gzip" in os.environ["HTTP_ACCEPT_ENCODING"]:
- if len(content) > 100:
- content = gzip.compress(content, compresslevel=5)
- print(f"Content-length: {len(content)}")
- print(f"Content-encoding: gzip")
- print()
- sys.stdout.flush()
- sys.stdout.buffer.write(content)
-def handleReq(dbCur):
+def handleReq(dbCur, environ):
# Get query params
- queryStr = os.environ["QUERY_STRING"] if "QUERY_STRING" in os.environ else ""
+ queryStr = environ["QUERY_STRING"] if "QUERY_STRING" in environ else ""
queryDict = urllib.parse.parse_qs(queryStr)
# Set vars from params
name = queryDict["name"][0] if "name" in queryDict else None
@@ -246,8 +236,7 @@ def handleReq(dbCur):
tree = queryDict["tree"][0] if "tree" in queryDict else "images"
# Check for valid 'tree'
if tree != None and re.fullmatch(r"trimmed|images|picked", tree) == None:
- respondJson(None)
- return
+ return None
# Get data of requested type
if reqType == "node":
toroot = queryDict["toroot"][0] if "toroot" in queryDict else None
@@ -257,8 +246,7 @@ def handleReq(dbCur):
tolNode = tolNodes[name]
childNodeObjs = lookupNodes(tolNode.children, tree, dbCur)
childNodeObjs[name] = tolNode
- respondJson(childNodeObjs)
- return
+ return childNodeObjs
else:
# Get ancestors to skip inclusion of
nodesToSkip = set()
@@ -279,8 +267,7 @@ def handleReq(dbCur):
tolNodes = lookupNodes([name], tree, dbCur)
if len(tolNodes) == 0:
if not ranOnce:
- respondJson(results)
- return
+ return results
print(f"ERROR: Parent-chain node {name} not found", file=sys.stderr)
break
tolNode = tolNodes[name]
@@ -297,8 +284,7 @@ def handleReq(dbCur):
results.update(childNodeObjs)
# Check if root
if tolNode.parent == None or tolNode.parent in nodesToSkip:
- respondJson(results)
- return
+ return results
else:
name = tolNode.parent
elif reqType == "sugg":
@@ -314,20 +300,27 @@ def handleReq(dbCur):
print(f"INFO: Invalid limit {suggLimit}", file=sys.stderr)
# Get search suggestions
if not invalidLimit:
- respondJson(lookupSuggs(name, suggLimit, tree, dbCur))
- return
+ return lookupSuggs(name, suggLimit, tree, dbCur)
elif reqType == "info":
infoResponse = lookupInfo(name, tree, dbCur)
if infoResponse != None:
- respondJson(infoResponse)
- return
+ return infoResponse
# On failure, provide empty response
- respondJson(None)
-def getTableSuffix(tree):
- return "t" if tree == "trimmed" else "i" if tree == "images" else "p"
-
-# Open db
-dbCon = sqlite3.connect(dbFile)
-dbCur = dbCon.cursor()
-# Handle request
-handleReq(dbCur)
+ return None
+def application(environ, start_response):
+ global dbFile
+ # Open db
+ dbCon = sqlite3.connect(dbFile)
+ dbCur = dbCon.cursor()
+ # Get response object
+ val = handleReq(dbCur, environ)
+ # Construct response
+ data = jsonpickle.encode(val, unpicklable=False).encode()
+ headers = [("Content-type", "application/json")]
+ if "HTTP_ACCEPT_ENCODING" in environ and "gzip" in environ["HTTP_ACCEPT_ENCODING"]:
+ if len(data) > 100:
+ data = gzip.compress(data, compresslevel=5)
+ headers.append(("Content-encoding", "gzip"))
+ headers.append(('Content-Length', str(len(data))))
+ start_response('200 OK', headers)
+ return [data]