3

I deployed a very simple Flask application called 'app' in a sub directory under root directory in Bluehost. Hopefully, example.com points to the homepage and example.com/app points to my Flask application. Actually, the Flask application works pretty fine when the script index.py looks like:

from flask import Flask

app = Flask(__name__)

@app.route('/', methods=['GET'])
def home():
    return 'Hello world'

if __name__ == "__main__":
    app.run()

But things went bad as I introduced a simple login functionality, with the doc structure and index.py look like:

doc structure:

public_html                     
|--app                          
     |--.htaccess
     |--index.fcgi
     |--index.py
     |--static
        |--login.html
     |--templates
        |--home.html

index.py:

from flask import Flask, url_for, request, render_template, redirect, session
app = Flask(__name__)

@app.route('/', methods=['GET'])
def home():
    if not session.get('user'):
        return redirect(url_for('login'))     #go to login page if not logined
    else:
        return render_template('home.html')   #otherwise go to home page

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        return app.send_static_file('login.html')
    else:
        user = request.form.get('user')
        password = request.form.get('password')
        if user == 'joy' and password == 'joy':
            session['user'] = user
            return render_template('home.html')
        else:
            return 'LOGIN FAILED'

if __name__ == "__main__":
    app.run()

However, accessing example.com/app led to a changed URL as example.com/login and a reasonable 404 error as example.com/login doesn't map to any document.

return redirect(url_for('login'))

The url_for('login') return example.com/login instead of example.com/app/login. That's why the latter version of index.py doesn't work. I tried so many things but didn't came across any fix. Please help. THanks!

My .htaccess:

Options +ExecCGI
AddHandler fcgid-script .fcgi
RewriteEngine On
#RewriteBase /app/        # Neither RewriteBase / or RewriteBase /app/  work
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.fcgi/$1 [QSA,L]

My index.fcgi:

import sys
sys.path.insert(0, '/path_to_my_python_site-packages')

from flup.server.fcgi import WSGIServer
from index import app

class ScriptNameStripper(object):
   def __init__(self, app):
       self.app = app

   def __call__(self, environ, start_response):
       environ['SCRIPT_NAME'] = ''
       return self.app(environ, start_response)

app = ScriptNameStripper(app)

if __name__ == '__main__':
    WSGIServer(app).run()
davidism
  • 121,510
  • 29
  • 395
  • 339
Joy Woo
  • 61
  • 1
  • 5
  • i would say [rewriteBase](http://stackoverflow.com/questions/704102/how-does-rewritebase-work-in-htaccess) is the way to go ([docs](http://httpd.apache.org/docs/current/mod/mod_rewrite.html)) – Nikos M. May 01 '15 at 16:54

2 Answers2

3

The following works for me now.

  1. Comment RewriteBase in .htaccess

  2. Updated index.py with a customized url_for

    from flask import Flask, redirect, url_for
    
    app = Flask(__name__)
    
    def strip_url(orig):
       return orig.replace('index.fcgi/', '')
    
    @app.route('/', methods=['GET'])
    def home():
        return redirect(strip_url(url_for('login')))
    
    @app.route('/login', methods=['GET'])
    def login():
        return 'please login'
    
    if __name__ == "__main__":
        app.run()
    

If a conclusion has to be made, I would like say official Flask fastcgi docs demands a RewriteRule to remove the ***.fcgi from the url which doesn't work for redirect initiated from within code.

Joy Woo
  • 61
  • 1
  • 5
1

Set APPLICATION_ROOT in your Flask config:

app.config["APPLICATION_ROOT"] = "/app"

Don't use RewriteBase, Flask needs to know about the URL root to generate URLs.

nathancahill
  • 10,452
  • 9
  • 51
  • 91
  • thank you! Just disabling RewriteBase improve it but came out different url rewrite problem, example.com/app was transformed example.com/app/index.fcgi, and the redirect url_for('login') directed to example.com/app/index.fcgi/login. It really works even not gracefully enough. So finally, my workaround is a customized url_for which find "index.fcgi" in the url and replace it with blank. – Joy Woo May 02 '15 at 01:19
  • So it doesn't work if you use `RewriteBase /` and `APPLICATION_ROOT = "/app"`? Your `strip_url` function shouldn't be necessary. – nathancahill May 02 '15 at 19:53