简体   繁体   English

如何在Flask webapp上获取apache来提供静态文件

[英]How to get apache to serve static files on Flask webapp

I'm getting a 500 internal error while trying to get Apache to serve my static files. 我在尝试让Apache提供静态文件时遇到500内部错误。

The application will be locally hosted (not www facing). 该应用程序将在本地托管(而不是面向www)。 There will be no DNS to resolve a 'www.domain.com' name. 没有DNS可以解析“www.domain.com”名称。 I want to be able to access the application by entering the IP address of the server when I'm on that network. 我想通过在该网络上输入服务器的IP地址来访问应用程序。

This is my httpd.conf file (I'm on RHEL): 这是我的httpd.conf文件(我在RHEL上):

<Directory /var/www/testapp>
  Order allow,deny
  Allow from all
</Directory>

WSGIScriptAlias / /var/www/testapp/service.wsgi

If I change the WSGIScriptAlias to WGSIScriptAlias /test /var/www/testapp/service.wsgi then I can view my static files when I type in the IP, but I still can't access the service.py script from [IP]/test. 如果我将WSGIScriptAlias更改为WGSIScriptAlias /test /var/www/testapp/service.wsgi那么当我输入IP时我可以查看我的静态文件,但是我仍然无法从[IP] /访问service.py脚本测试。

In any case, I want to be able to service all GET/POST requests with the service.py script so I want my alias to start at / , not some other place. 在任何情况下,我希望能够使用service.py脚本为所有GET / POST请求提供服务,因此我希望我的别名从/开始,而不是从其他地方开始。

All my static files are in /var/www/html (Apache was automatically displaying these files before I messed with the httpd.conf, now I'm just getting a 500). 我的所有静态文件都在/ var / www / html中(Apache在我使用httpd.conf之前自动显示这些文件,现在我只是获得了500)。

This is my service.wsgi: 这是我的service.wsgi:

import sys
sys.path.insert(0, '/var/www/testapp')
from service import app as application

This is my service.py: 这是我的service.py:

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello(environ, start_response):
    status = '200 OK'
    output = "Hello"
    response_headers = [('Content-type', 'text/plain'), ('Content-length', str(len(output)))]
    start_response(status, response_headers)
    return output

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

Do I need keep my .wsgi files in the /var/www/html directory as well? 我是否还需要将我的.wsgi文件保存在/ var / www / html目录中? Or can they go in a different folder? 或者他们可以进入不同的文件夹? I can see that there might be some conflict between the message I am sending to the server ('Hello') and the static files that are already in the /var/www/html/ directory. 我可以看到我发送到服务器的消息('Hello')和已经在/ var / www / html /目录中的静态文件之间可能存在一些冲突。 That's why I tried setting the alias to /test but that didn't work either. 这就是为什么我尝试将别名设置为/test但这也不起作用。

I just want my Flask application to service GET/POST requests and want apache to serve all the static files. 我只是想让我的Flask应用程序为GET / POST请求提供服务,并希望apache能够提供所有静态文件。

Fixing the 500 errors 修复500错误

You are currently getting 500 errors because your handler is a basic WSGI handler, but Flask handlers are not WSGI handlers (Flask / Werkzeug abstracts all that for you). 您当前收到500个错误,因为您的处理程序是一个基本的WSGI处理程序,但Flask处理程序不是WSGI处理程序(Flask / Werkzeug为您提取所有这些内容)。 Change your handler to: 将处理程序更改为:

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

and the 500 errors should go away. 500错误应该消失。

Serving static files with Apache 使用Apache提供静态文件

The following techniques can be used when your application is serving the root of the domain ( / ), depending on whether you are using WSGIScriptAlias or AddHandler . 当您的应用程序为域的根目录( / )提供服务时,可以使用以下技术,具体取决于您使用的是WSGIScriptAlias还是AddHandler

When using WSGIScriptAlias 使用WSGIScriptAlias

When using the WSGIScriptAlias to mount a WSGI application at / you can use an Apache Alias directive to ensure that certain sub-routes are not handled by WSGIScriptAlias (this is further documented in mod_wsgi 's wiki as well ): 当使用WSGIScriptAlias/上安装WSGI应用程序时,您可以使用Apache Alias指令来确保WSGIScriptAlias 处理某些子路由 (这也在mod_wsgi的wiki中进一步记录 ):

Alias "/static/" "/path/to/app/static/"
<Directory "/path/to/app/static/">
  Order allow,deny
  Allow from all
</Directory>

If you also want to support blueprint static folders as well you'll also need to use the AliasMatch directive: 如果您还想支持蓝图静态文件夹,您需要使用AliasMatch指令:

AliasMatch "(?i)^/([^/]+)/static/(.*)$" "/path/to/app/blueprints-root/$1/static/$2"
<Directory ~ "/path/to/app/blueprints-root/[^/]+/static/.*">
  Order allow,deny
  Allow from all
</Directory>

See also: The Directory directive. 另请参见: Directory指令。

When using AddHandler 使用AddHandler

As Graham Dumpleton has pointed out in the comments, you can use mod_rewrite to pass requests off to Python if and only if a file does not exist in DocumentRoot . 正如Graham Dumpleton在评论中指出的那样,当且仅当DocumentRoot中不存在文件时, 您可以使用mod_rewrite将请求传递给Python。 Quoting from the linked docs: 引用链接的文档:

When using the AddHandler directive, with WSGI applications identified by the extension of the script file, the only way to make the WSGI application appear as the root of the server is to perform on the fly rewriting of the URL internal to Apache using mod_rewrite. 使用AddHandler指令时,由脚本文件扩展名标识的WSGI应用程序,使WSGI应用程序显示为服务器根目录的唯一方法是使用mod_rewrite即时执行Apache内部URL的重写。 The required rules for mod_rewrite to ensure that a WSGI application, implemented by the script file 'site.wsgi' in the root directory of the virtual host, appears as being mounted on the root of the virtual host would be: mod_rewrite所需的规则,以确保由虚拟主机的根目录中的脚本文件“site.wsgi”实现的WSGI应用程序显示为安装在虚拟主机的根目录上,将是:

 RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ /site.wsgi/$1 [QSA,PT,L] 

Do note however that when the WSGI application is executed for a request the 'SCRIPT_NAME' variable indicating what the mount point of the application was will be '/site.wsgi'. 但请注意,当为请求执行WSGI应用程序时,“SCRIPT_NAME”变量指示应用程序的挂载点将是“/site.wsgi”。 This will mean that when a WSGI application constructs an absolute URL based on 'SCRIPT_NAME', it will include 'site.wsgi' in the URL rather than it being hidden. 这意味着当WSGI应用程序构建基于“SCRIPT_NAME”的绝对URL时,它将在URL中包含“site.wsgi”而不是隐藏它。 As this would probably be undesirable, many web frameworks provide an option to override what the value for the mount point is. 由于这可能是不合需要的,许多Web框架提供了一个覆盖挂载点值的选项。 If such a configuration option isn't available, it is just as easy to adjust the value of 'SCRIPT_NAME' in the 'site.wsgi' script file itself. 如果没有这样的配置选项,那么在'site.wsgi'脚本文件本身中调整'SCRIPT_NAME'的值也同样容易。

 from your.app import app # Your Flask app import posixpath def application(environ, start_response): # Wrapper to set SCRIPT_NAME to actual mount point. environ['SCRIPT_NAME'] = posixpath.dirname(environ['SCRIPT_NAME']) if environ['SCRIPT_NAME'] == '/': environ['SCRIPT_NAME'] = '' return app(environ, start_response) 

This wrapper will ensure that 'site.wsgi' never appears in the URL as long as it wasn't included in the first place and that access was always via the root of the web site instead. 这个包装器将确保“site.wsgi”永远不会出现在URL中,只要它不包含在第一位,并且该访问始终通过网站的根目录而不是。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM