Flask w/ Apache & FCGI 路由问题

Flask w/ Apache & FCGI routing problems

所以我一直在使用 Flask 和 Bootstrap 在 Apache 服务器上工作。我已经到了可以访问应用程序并使用以下路线呈现 "first" 或 "main" 模板的地步:

来自 view.py:

@app.route('/')
def fn_home():
    return render_template("main.html")

不幸的是,每次尝试从 main.html 路由到另一个 webpage/function 都会失败。我在导航栏列表 href 中使用 "url_for" 函数,试图让 Flask 向 Apache 提供 xls-upload.html 网页。

来自 main.html:

<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
  <ul class="nav navbar-nav">
    <li><a href="{{ url_for('upload') }}">Upload Spreadsheets </a></li>

来自 view.py:

@app.route('/upload')
def upload():
    return render_template("xls-upload.html")

看起来函数正在使用,因为 URL 更改为 http://myapp/upload,但是 html 页面不是函数 rendered/returned - 相反我收到 404 "Not Found"。我似乎无法 return 函数中的任何内容,甚至 return "Hello World".

它 "seems" 就像 Apache 一样,实际上是在尝试解析 http://myapp/upload 路径,而不是向 Flask 应用程序打开一个套接字,然后通过该套接字发送 html。我不确定这是否是一个 FCGI 问题,如果我遗漏了一个 relative/absolute 路径问题,误解了 Flask 的一般工作方式,或者所有问题的某种组合,等等

我是 Flask 的新手,所以我希望有人能一路帮助我,因为我真的觉得我已经走到了死胡同。

提前致谢!

我的 flask 应用程序结构如下:

以下是我的适用文件:

1) /etc/httpd/conf.d/myapp:

<VirtualHost *:80>
    ServerAdmin webmaster@localhost

    DocumentRoot /var/www/cgi-bin/myapp/static/
    ServerName myapp

    Alias /static/ /var/www/cgi-bin/myapp/static/
    ScriptAlias / /var/www/cgi-bin/myapp/start.fcgi

    <Directory "var/www/cgi-bin/myapp">
        AllowOverride None
        Order allow,deny
        Allow from all
        AuthType Basic
        AuthUserFile /etc/httpd/.htpasswd
        AuthName 'Enter Password'
        Require valid-user
    </Directory>

</VirtualHost>

2) /var/www/cgi-bin/myapp/start.fcgi:

#!/usr/bin/python

#  IMPORTS:

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

if __name__ == '__main__':
    WSGIServer(app).run()

3) /var/www/cgi-bin/myapp/view.py:

#!/usr/bin/python

# IMPORTS:
import os
from flask import Flask, render_template, url_for, request, session, redirect
from werkzeug import secure_filename

# STATIC VARIABLES
UPLOAD_FOLDER = 'var/www/cgi-bin/myapp/xls-dir'
ALLOWED_EXTENSIONS = set(['xls'])

## flask:
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER

# FUNCTIONS
def fn_allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS

@app.route('/')
def fn_home():
    return render_template("main.html")

@app.route('/upload')
def upload():
    return render_template("xls-upload.html")
    #return "HI there"

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0')

4) /var/www/cgi-bin/myapp/templates/main.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
    <title>ALG Tools HOME</title>

    <!-- Bootstrap -->
    <link href="{{ url_for('static', filename = 'css/bootstrap.min.css') }}" rel="stylesheet">
  </head>
<nav class="navbar navbar-default">
  <div class="container-fluid">
    <!-- Brand and toggle get grouped for better mobile display -->
    <div class="navbar-header">
      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="/">ALG Tool - HOME</a>
    </div>

    <!-- Collect the nav links, forms, and other content for toggling -->
    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
      <ul class="nav navbar-nav">
        <li><a href="{{ url_for('upload') }}">Upload Spreadsheets </a></li>
        <li><a href="/xls-download.html">Download Spreadsheets</a></li>
        <li><a href="/cfg-generate.html">Generate Configs</a></li>
      </ul>
    </div>
  </div>
</nav>

  <body>
    <h2>ALG stuff</h2>

    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
    <!-- Include all compiled plugins (below), or include individual files as needed -->
    <script src="{{ url_for('static', filename = 'js/bootstrap.min.js') }}"></script>
  </body>

</html>

5) /var/www/cgi-bin/myapp/templates/xls-upload.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
    <title>ALG XLS Upload</title>

    <!-- Bootstrap -->
    <link href="{{ url_for('static', filename = 'css/bootstrap.min.css') }}" rel="stylesheet">
  </head>
<nav class="navbar navbar-default">
  <div class="container-fluid">
    <!-- Brand and toggle get grouped for better mobile display -->
    <div class="navbar-header">
      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="/">ALG Tool - HOME</a>
    </div>

    <!-- Collect the nav links, forms, and other content for toggling -->
    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
      <ul class="nav navbar-nav">
        <li><a href="/xls-upload.html">Upload Spreadsheets </a></li>
        <li><a href="/xls-download.html">Download Spreadsheets</a></li>
        <li><a href="/cfg-generate.html">Generate Configs</a></li>
      </ul>
    </div>
  </div>
</nav>

  <body>
    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
    <!-- Include all compiled plugins (below), or include individual files as needed -->
    <script src="{{ url_for('static', filename = 'js/bootstrap.min.js') }}"></script>

  </body>

</html>

FCGI 并不是真正推荐的 Python 网络应用服务方式。您应该研究 运行ning WSGI 的多种方法之一。

但是,假设您出于某种原因需要执行此操作,则您遇到了一个小配置问题,这就是问题的原因;您需要在 ScriptAlias 路径上添加尾部斜杠。

ScriptAlias / /var/www/cgi-bin/myapp/start.fcgi/

有了这个,Apache 将把完整路径传递给 start.fcgi 脚本,而不是替换它。

请注意,即使使用 FCGI,您也不应将您的应用程序代码放在 cgi-bin 中。它不需要存在,因为它不像 CGI 应用程序那样由 Web 服务器 运行。事实上,您的代码根本不应该在 /var/www 之下。