9

我使用烧瓶 Web 框架为我的体育俱乐部编写了一个 Web 应用程序。我使用内置测试服务器在本地机器上完成了所有操作。

知道他们告诉我将其部署在 1&1 共享托管网络空间上。他们有 python 支持,但似乎他们只允许 CGI 运行 python 脚本。

我试过这个教程:flask via CGI

直到现在我都忽略了重写的东西。对我的 CGI 脚本的所有请求都导致了 404 错误。我在应用程序中修改了我的 404 处理程序以返回request.path. 当我请求 /foo/runserver.cgi/ 它返回 / 作为输出。我不知道为什么它不提供索引视图。它不适用于任何视图,我总是得到 404。

亲切的问候,塞巴斯蒂安

4

3 回答 3

17

我写信是在将近一年后提供一个答案,因为给定的答案不完整,并且因为省略 /$1 的建议是错误的。使用字符串“deploy flask on cgi”通过 Internet 搜索可以访问的其他 stackoverflow 线程也没有令人满意的解决方案而结束。

首先,我的 .htaccess 文件与引用的“flask via CGI”文档中的完全一样,除了必须删除 RewriteCond 第二行中的注释,因为在 .htaccess 中,任何注释都必须占据一整行。

我将 .htaccess 文件放在 public_html 文档根文件夹中,我的 cgi 脚本是 /home/myusername/public_html/scgi-bin/moc/cgiappserver-prod.cgi。

当然是 Python,顶部的 shebang 最好是正确的。在我的 ISP,他们使用 cpanel,它有一个 CGI 包装器,他们称之为“scgi”。不幸的是,这不是真的。因此,出于运行 Flask 的目的,将其视为普通 CGI。

我应该补充一点,我只有一个共享主机帐户。

这是我的 cgiappserver-prod.cgi 文件:

#!/home/myusername/local/bin/python
import cgitb; cgitb.enable()  # This line enables CGI error reporting
from wsgiref.handlers import CGIHandler
import traceback
from settings import LGGR

app = None
try:
    import moc
    app = moc.app
except Exception, e:
    LGGR.info( traceback.format_exc([10]) )
    LGGR.info( 'Problem in cgiappserver-prod with moc import: %s' % e )

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)

try:
    CGIHandler().run(app)
except Exception, e:
    LGGR.info( traceback.format_exc([10]) )
    LGGR.info( 'Problem in cgiappserver-prod with CGIHandler().run(): %s' % e )

所以我的应用程序分布在几个文件中,上面的代码中特别显示了 setting.py 和 moc.py。

我的几个小时陷入困境的部分原因是我阅读了关于这个主题的所有无益的帖子,但主要是因为我没有足够早地得到错误消息。(我可以访问 ISP 提供的错误日志,但它很少有帮助。)

首先,我已经确认 cgitb.enable() 函数有效。我故意拼错了 wsgiref 并看到了一个漂亮的错误页面,我已经注释掉了 cgitb (cgi traceback) 行,看到错误消息变成了无用的 500 状态代码。

请注意,我还在 settings.py 中设置了一个记录器,一个旋转文件记录器 LGGR。有了它,我发现我必须做一些额外的事情——这里没有显示——告诉 Python 解释器 sqlite3 库在哪里。

此外,您可以简单地使用打印语句,CGI 上引用的 Flask 文档说:

  • 使用 CGI,您还必须确保您的代码不包含任何打印语句,或者 sys.stdout 被不写入 HTTP 响应的内容覆盖。

没错,但在调试时查看打印写入 HTTP 响应会很有帮助。

最后,当我最终让它工作时,浏览器的位置框很遗憾地有 www.mysite.com/scgi-bin/moc/cgiappserver-prod.cgi/contact 之类的东西,而我真的只需要 www.mysite.com /接触。

解决方法是 cgiappserver-prod.cgi 中的 ScriptNameStripper 类。我从其他 Flask 文档中得到它。

于 2014-07-20T07:40:27.560 回答
3

我找到了解决办法!我离开了/$1.htaccess并稍微修改了 werkzeug,因为 CGI 中的环境变量在 WSGI 应用程序中的命名有点不同。我会通知 werkzeug 开发人员,也许他会将我的解决方案包含在 werkzeug 中。

于 2013-08-17T23:46:52.347 回答
2

我将尝试展示我所做的并且它在 Godaddy 共享主机帐户中工作:

在 MYSITE 文件夹的 cgi-bin 文件夹中,我添加了以下 cgi 文件:

#!/home/USERNAME/.local/bin/python3
from wsgiref.handlers import CGIHandler

from sys import path
path.insert(0, '/home/USERNAME/public_html/MYSITE/')
from __init__ import app

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

   def __call__(self, environ, start_response):
       environ['SERVER_NAME'] = ""
       environ['SERVER_PORT'] = "80"
       environ['REQUEST_METHOD'] = "GET"
       environ['SCRIPT_NAME'] = ""
       environ['PATH_INFO'] = "/"
       environ['QUERY_STRING'] = ""
       environ['SERVER_PROTOCOL'] = "HTTP/1.1"
       return self.app(environ, start_response)

if __name__ == '__main__':
    app.wsgi_app = ProxyFix(app.wsgi_app)
    CGIHandler().run(app)

如您所见,MYSITE 文件夹中的init文件包含烧瓶应用程序。

最重要的是设置权限。我将此文件夹权限设置为 755 以及“/home/USERNAME/.local/bin/python3”文件夹!请记住,系统需要此权限才能打开烧瓶和所有 python 包。

对于调试,我建议通过 ssh 终端访问您的站点并单独运行 CGI。如果它有效,但在网络上无效,这意味着您可能需要授予更多权限,或者您写错了 .htaccess 文件。

要打开 cgi,我在 MYSITE 文件夹中有以下 .htaccess 文件:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f 
RewriteRule ^(.*)$ /home/USERNAME/public_html/MYSITE/cgi-bin/application.cgi/$1 [L]

因此,当有人进入您的页面时,它将呈现 cgi 文件。

于 2018-01-13T22:36:33.177 回答