Skip to content
Snippets Groups Projects
Unverified Commit 08550275 authored by Sebastian Höffner's avatar Sebastian Höffner
Browse files

Removes UA-check.

Removes /gui endpoint. The gui is now presented at /.
Adds /parse endpoint. This endoints receives /'s former functionality.
Adapted README to reflect the new URLs.
parent eb474f5e
No related branches found
No related tags found
No related merge requests found
......@@ -4,14 +4,14 @@ This repository builds a small [nginx](https://nginx.org/)-webserver and python
After an initial `docker-compose up`, the service can be queried using a simple POST request, e.g. using curl:
$ curl --data "Take the cup." localhost
$ curl --data "Take the cup." localhost/parse
{"version": "1.1.0", "application": "web-openccg", "uuid": "5fbcbc0d-c75e-4278-aa85-37a745847ae8", "sentence": "take the cup", "parses": {"smain": "@x1:gum-OrientationChange( <mood>imp ^ <gs-direction>(x2:gs-GeneralizedLocation ^ <gs-hasSpatialModality>(w2:slm-Cup ^ cup ^ <det>the ^ <ident>specific ^ <quant>singular)) ^ <gum-processInConfiguration>(w0:slm-Moving ^ slm-Taking))", "smain/0": "@x1:gum-OrientationChange( <mood>imp ^ <gs-direction>(x2:gs-GeneralizedLocation ^ <gs-hasSpatialModality>(w2:slm-Cup ^ cup ^ <det>the ^ <ident>specific ^ <quant>singular)) ^ <gum-processInConfiguration>(w0:slm-Taking ^ slm-Taking))", "smain/.r": "@x1:gs-AffectingDirectedMotion( <mood>imperative ^ <gs-route>x2 ^ <gum-actee>(w2:slm-Cup ^ cup ^ <det>the ^ <ident>specific ^ <quant>singular) ^ <gum-processInConfiguration>(w0:slm-Moving ^ slm-Taking))", "smain/.r/0": "@x1:gs-AffectingDirectedMotion( <mood>imperative ^ <gs-route>x2 ^ <gum-actee>(w2:slm-Cup ^ cup ^ <det>the ^ <ident>specific ^ <quant>singular) ^ <gum-processInConfiguration>(w0:slm-Taking ^ slm-Taking))"}, "http_status": 200, "json_parses": {"smain": {"nominal": "x1:gum-OrientationChange", "roles": [{"type": "mood", "target": "imp"}, [{"type": "gs-direction", "target": {"variable": "x2:gs-GeneralizedLocation", "roles": {"type": "gs-hasSpatialModality", "target": {"variable": "w2:slm-Cup", "roles": [{"entity": "cup"}, {"type": "det", "target": "the"}, {"type": "ident", "target": "specific"}, {"type": "quant", "target": "singular"}]}}}}, {"type": "gum-processInConfiguration", "target": {"variable": "w0:slm-Moving", "roles": {"entity": "slm-Taking"}}}]]}, "smain/0": {"nominal": "x1:gum-OrientationChange", "roles": [{"type": "mood", "target": "imp"}, [{"type": "gs-direction", "target": {"variable": "x2:gs-GeneralizedLocation", "roles": {"type": "gs-hasSpatialModality", "target": {"variable": "w2:slm-Cup", "roles": [{"entity": "cup"}, {"type": "det", "target": "the"}, {"type": "ident", "target": "specific"}, {"type": "quant", "target": "singular"}]}}}}, {"type": "gum-processInConfiguration", "target": {"variable": "w0:slm-Taking", "roles": {"entity": "slm-Taking"}}}]]}, "smain/.r": {"nominal": "x1:gs-AffectingDirectedMotion", "roles": [{"type": "mood", "target": "imperative"}, [{"type": "gs-route", "target": "x2"}, [{"type": "gum-actee", "target": {"variable": "w2:slm-Cup", "roles": [{"entity": "cup"}, {"type": "det", "target": "the"}, {"type": "ident", "target": "specific"}, {"type": "quant", "target": "singular"}]}}, {"type": "gum-processInConfiguration", "target": {"variable": "w0:slm-Moving", "roles": {"entity": "slm-Taking"}}}]]]}, "smain/.r/0": {"nominal": "x1:gs-AffectingDirectedMotion", "roles": [{"type": "mood", "target": "imperative"}, [{"type": "gs-route", "target": "x2"}, [{"type": "gum-actee", "target": {"variable": "w2:slm-Cup", "roles": [{"entity": "cup"}, {"type": "det", "target": "the"}, {"type": "ident", "target": "specific"}, {"type": "quant", "target": "singular"}]}}, {"type": "gum-processInConfiguration", "target": {"variable": "w0:slm-Taking", "roles": {"entity": "slm-Taking"}}}]]]}}}
Or, as an example, using Python [requests](http://docs.python-requests.org/en/master/):
```python
import requests
print(requests.post('http://localhost', data={'sentence': 'Take the cup.'}).json())
print(requests.post('http://localhost/parse', data={'sentence': 'Take the cup.'}).json())
```
Note that is is not production ready, as it is really slow and not optimized:
......@@ -22,17 +22,17 @@ Instead of keeping one (or multiple) instances of OpenCCG running to query them
### Querying
To query the service visually, just open your browser at [http://localhost/gui](http://localhost/gui).
To query the service visually, just open your browser at [http://localhost/](http://localhost/).
Otherwise, use curl, wget, or e.g. python requests to query web-openccg via the command line or your application.
If your client allows to build your request body manually, like curl, just put the sentence inside:
curl --data "Take the cup." localhost
curl --data "Take the cup." localhost/parse
However, many high level frameworks like python requests usually use a
key-value mechanism for post data. In this case, use the key `sentence`:
requests.post('http://localhost', data={'sentence': 'Take the cup.'})
requests.post('http://localhost/parse', data={'sentence': 'Take the cup.'})
### Response format
......
import json
import uuid
from flask import Flask, render_template, request, redirect
from flask import Flask, render_template, request
import wccg
app = Flask(__name__)
def is_non_gui_agent(ua_string):
"""Returns True for a few specific matches for User-Agent strings.
This is a very simple heuristic to distinguish between browser agents
and command line or programmatical agents, and the list might grow.
Returns:
True if the User-Agent string contains either of a set of possible
user agents, for example curl/, wget/ or python-requests/.
"""
uas = ('python-requests/', 'curl/', 'wget/')
ua_string = ua_string.lower()
return any(ua in ua_string for ua in uas)
def create_response(sentence):
"""Prepares a response.
......@@ -46,47 +31,39 @@ def create_response(sentence):
return response
@app.route('/gui', methods=['GET', 'POST'])
def gui():
"""Presents a simple input form to a browser user.
"""
sentence = request.form.get('sentence')
response = create_response(sentence)
response = json.dumps(response, indent=4)
return render_template('form.html', sentence=sentence, response=response)
@app.route('/parse', methods=['POST'])
def parse():
"""Handles parse requests.
@app.route('/', methods=['GET', 'POST'])
def index():
"""This method handles / requests.
If the request is from a GUI client (that is, is_non_gui_agent is False),
a redirect to /gui is returned.
Else, if the requests is a GET request or contains no POST data,
If the requests is a GET request or contains no POST data,
an error (501 or 400, respectively) is returned.
Otherwise, the sentence's parse is returned. If wccg was unable to parse
the sentence, its answer is returned alongside a 422 status code.
"""
ua = request.headers.get('User-Agent')
if is_non_gui_agent(ua):
if request.method == 'GET':
return json.dumps(dict(error="Use POST.", http_status=501)), 501
try:
key = next(request.values.keys())
except StopIteration:
key = None
# Get sentence from form field or use the first key.
# The first key could be send e.g. by
# curl --data "This is the sentence." 127.0.0.1:5000
sentence = request.form.get(key) or key
response = create_response(sentence)
return json.dumps(response), response['http_status']
return redirect('/gui', code=307)
if request.method == 'GET':
return json.dumps(dict(error="Use POST.", http_status=501)), 501
try:
key = next(request.values.keys())
except StopIteration:
key = None
# Get sentence from form field or use the first key.
# The first key could be send e.g. by
# curl --data "This is the sentence." 127.0.0.1:5000
sentence = request.form.get(key) or key
response = create_response(sentence)
return json.dumps(response), response['http_status']
@app.route('/', methods=['GET', 'POST'])
def index():
"""This method shows a minimal user interface."""
sentence = request.form.get('sentence')
response = create_response(sentence)
response = json.dumps(response, indent=4)
return render_template('form.html', sentence=sentence, response=response)
if __name__ == '__main__':
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment