首页 > 在Bluehost的子目录上部署Flask碰到url重定向难题

在Bluehost的子目录上部署Flask碰到url重定向难题

Bluehost的主机一般web的根目录是public_html(别名是www)。由于根目录下面放的是网站首页,不能乱动,因此为了部署新的应用,我在public_html下建了app这个目录。

  1. 在app下设置.htaccess,内容如下:
Options +ExecCGI
AddHandler fcgid-script .fcgi
RewriteEngine On
RewriteBase /app/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.fcgi/$1 [QSA,L]

  1. 在app下设置index.fcgi,内容如下:
#!/mypath_to_python
import sys
sys.path.insert(0, '/mypath_to_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()
  1. 部署一个简单的hello world应用,index.py,内容如下:
from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

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

输入http://abc.com/app,一切正常。

于是我开始增加一个登录功能,当用户访问首页http://abc.com/app时,如果发现用户没有登录,自动跳转到http://abc.com/app/login。于是我改写了index.py如下:

from flask import Flask, request, url_for, render_template, redirect, session
app = Flask(__name__, static_url_path='/static')

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

@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'

部署的目录结构如下:
public_html (对应abc.com)
|--app (这里对应abc.com/app)
|--.htaccess
|--index.fcgi
|--index.py
|--static
|--login.html
|--templates
|--home.html

就这么一个简单的应用,部署上去以后,访问http://abc.com/app,本来期望的效果是直接跳转到http://abc.com/app/login,加载静态登陆页面login.html,让用户属于登录信息。但实际得到的效果确是跳转到http://abc.com/login,导致了404找不到页面的错误。我试了很多很多方法,都没搞定,求助大家。


不要尝试把 Web 程序挂载到子目录,除非这个 Web 程序显式地支持这样做。

一种可行的办法是挂载到特定的域名;另一种办法是通过配置项使得 Flask 里使用修改过的 URL,比如定义

URL_PREFIX = '/app'

然后在路由的时候使用 URL_PREFIX + '/login' 这样。你可以自定义一个 blueprint,覆写其 route 方法来自动给 endpoint 添加前缀。

当然还有个办法是自己实现 url_for,但是你不一定能做好。

更新

试试设置 APPLICATION_ROOT 配置项。

【热门文章】
【热门文章】