0

I am trying to use WSGI with a URL that I need to be able to POST to under Apache 2 (using flask). I am able to run my .wsgi independently of Apache (python cfg.wsgi) and it handles GET and POST requests correctly (tested with curl) but it does not operate when run under Apache: a curl GET request to the relevant URL (/watchdog.cfg) returns "404 Not Found" (and if I remove the WSGI mapping the GET works absolutely fine, fully within Apache, but then of course I don't get the POST facility I'm after)

Apache is loading the .wsgi file (its error log says so and a debug print at the top of the .wsgi file appears in a debug log), so Python paths and interpreters are likely correct; the issue, it seems, is that the .wsgi routing function is not being called by Apache (i.e. a debug print just inside the application function does not appear in the debug log when the URL in question (/watchdog.cfg) is requested).

My Apache .conf file is:

<VirtualHost *:80>
    DocumentRoot /home/http/
    WSGIScriptAlias /watchdog.cfg /home/http/cfg.wsgi
    <Directory /home/http>
        AllowOverride none
        Require all granted
    </Directory>
</VirtualHost>

apache2ctl -M | grep wsgi returns "wsgi_module (shared)", so I believe that Apache has the WSGI module installed. The file watchdog.cfg has permissions 0644, the file cfg.wsgi has permissions 0755.

My cfg.wsgi file is:

from flask import Flask, request, send_file
from os import path

FILE_NAME = 'watchdog.cfg'

application = Flask(__name__)

@application.route('/' + FILE_NAME, methods=['GET', 'POST'])
def cfg():
    file_path = '/home/http/' + FILE_NAME;
    if request.method == 'POST':
        jsonString = request.json
        with open(file_path, 'w') as f:
            f.write(jsonString)
        return "File updated successfully.", 200
    elif request.method == 'GET':
        if path.exists(file_path):
            return send_file(file_path, mimetype='application/json')
        else:
            return "File not found.", 404

if __name__ == '__main__':
    application.run(host='0.0.0.0', port=80)

This is on Raspbian Linux. Any suggestions as to why my routing function is not being called by Apache?

1
  • FYI, I have now written a version of cfg.wsgi that works without Flask (all other settings the same), so the problem seems likely to be with how I have constructed the interface into Flask. Commented Jan 18 at 0:02

1 Answer 1

0

For the record, here is the Flask-less version of my cfg.wsgi which did work (same Apache .conf file contents):

from os import path
import logging

FILE_NAME = 'watchdog.cfg'

def application(environ, start_response):
    file_path = path.join(path.dirname(path.realpath(__file__)), FILE_NAME)

    try:
        if environ['REQUEST_METHOD'] == 'GET':
            if path.exists(file_path):
                start_response('200 OK', [('Content-Type', 'application/json')])
                with open(file_path, 'r') as f:
                    json_data = f.read()
                return [str.encode(json_data)]
            else:
                start_response('404 File Not Found', [('Content-Type', 'text/plain')])
                return [b'File Not Found.']

        elif environ['REQUEST_METHOD'] == 'POST':
            try:
                content_length = int(environ.get('CONTENT_LENGTH', 0))
            except ValueError:
                start_response('400 Bad Request', [('Content-Type', 'text/plain')])
                return [b'Invalid Content-Length']

            post_data = environ['wsgi.input'].read(content_length)
            try:
                with open(file_path, 'w') as f:
                    f.write(post_data.decode('utf-8'))
                start_response('200 OK', [('Content-Type', 'text/plain')])
                return [b'File uploaded successfully!']
            except IOError as e:
                start_response('500 Internal Server Error', [('Content-Type', 'text/plain')])
                return [b'Failed to write file.']

        else:
            start_response('405 Method Not Allowed', [('Content-Type', 'text/plain')])
            return [b'Method Not Allowed.']

    except Exception as e:
        start_response('500 Internal Server Error', [('Content-Type', 'text/plain')])
        return [b'Internal Server Error.']
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.