Skip to content

Commit

Permalink
Merge pull request #3 from yanokwa/switch-to-waitress
Browse files Browse the repository at this point in the history
Switch to waitress to support chunked encoding
  • Loading branch information
yanokwa authored Nov 7, 2019
2 parents 402715a + 63a12c1 commit 6cc31e9
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 53 deletions.
6 changes: 4 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
FROM tiangolo/uwsgi-nginx-flask:python3.7-alpine3.8
FROM python:3.8-alpine

COPY requirements.txt /tmp/
RUN pip install --upgrade pip
RUN pip install --requirement /tmp/requirements.txt

RUN apk --update add openjdk8-jre-base

COPY ./app /app
WORKDIR /app

CMD ["waitress-serve", "--port=80", "--call", "main:app"]
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pyxform-http is a Flask-based web service that uses pyxform to convert a XLSForm
# Run locally
```
pip install --requirement requirements.txt
FLASK_APP=app/main.py FLASK_DEBUG=1 flask run
FLASK_APP=app/main.py:app FLASK_DEBUG=1 flask run
```

# Run in Docker
Expand All @@ -19,9 +19,9 @@ docker run --detach --name pyxform-http --publish 5000:80 pyxform-http

# Test forms

A form that converts successfully
A form that converts successfully (with chunked encoding!)
```
curl --request POST --header "X-XlsForm-FormId-Fallback: pyxform-clean" --data-binary @test/pyxform-clean.xlsx http://127.0.0.1:5000/api/v1/convert
curl --request POST --header "X-XlsForm-FormId-Fallback: pyxform-clean" --header 'Transfer-Encoding: chunked' --data-binary @test/pyxform-clean.xlsx http://127.0.0.1:5000/api/v1/convert
```

A form that fails to convert and returns a pyxform error
Expand Down
92 changes: 48 additions & 44 deletions app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,50 +5,54 @@
from flask import Flask, jsonify, request, escape
from pyxform import xls2xform

app = Flask(__name__)
logger = logging.getLogger(__name__)


@app.route("/")
def index():
return "Welcome to the pyxform-http! Make a POST request to '/api/v1/convert' to convert an XLSForm to an ODK XForm."


@app.route("/api/v1/convert", methods=["POST"])
def post():

xlsform_formid_fallback = sanitize(request.headers.get("X-XlsForm-FormId-Fallback"))
if xlsform_formid_fallback is None:
xlsform_formid_fallback = "tmp"

with TemporaryDirectory() as temp_dir_name:
try:
with open(
os.path.join(temp_dir_name, xlsform_formid_fallback + ".xml"), "w+"
) as xform, open(
os.path.join(temp_dir_name, xlsform_formid_fallback + ".xlsx"), "wb"
) as xlsform:
xlsform.write(request.get_data())
convert_status = xls2xform.xls2xform_convert(
xlsform_path=str(xlsform.name),
xform_path=str(xform.name),
validate=True,
pretty_print=False,
)

if convert_status:
logger.warning(convert_status)

if os.path.isfile(xform.name):
return response(
status=200, result=xform.read(), warnings=convert_status

def app():
app = Flask(__name__)
logger = logging.getLogger(__name__)

@app.route("/")
def index():
return "Welcome to the pyxform-http! Make a POST request to '/api/v1/convert' to convert an XLSForm to an ODK XForm."

@app.route("/api/v1/convert", methods=["POST"])
def post():

xlsform_formid_fallback = sanitize(
request.headers.get("X-XlsForm-FormId-Fallback")
)
if xlsform_formid_fallback is None:
xlsform_formid_fallback = "tmp"

with TemporaryDirectory() as temp_dir_name:
try:
with open(
os.path.join(temp_dir_name, xlsform_formid_fallback + ".xml"), "w+"
) as xform, open(
os.path.join(temp_dir_name, xlsform_formid_fallback + ".xlsx"), "wb"
) as xlsform:
xlsform.write(request.get_data())
convert_status = xls2xform.xls2xform_convert(
xlsform_path=str(xlsform.name),
xform_path=str(xform.name),
validate=True,
pretty_print=False,
)
else:
return response(error=convert_status)

except Exception as e:
logger.error(e)
return response(error=str(e))
if convert_status:
logger.warning(convert_status)

if os.path.isfile(xform.name):
return response(
status=200, result=xform.read(), warnings=convert_status
)
else:
return response(error=convert_status)

except Exception as e:
logger.error(e)
return response(error=str(e))

return app


def sanitize(string):
Expand All @@ -60,5 +64,5 @@ def response(status=400, result=None, warnings=None, error=None):


if __name__ == "__main__":
# Only for debugging while developing
app.run(host="0.0.0.0", debug=True, port=80)
app = app()
app.run()
3 changes: 0 additions & 3 deletions app/uwsgi.ini

This file was deleted.

3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
Flask==1.1.0
Flask==1.1.1
waitress==1.2.1
pyxform==0.15.1

0 comments on commit 6cc31e9

Please sign in to comment.