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). There will be no DNS to resolve a 'www.domain.com' name. I want to be able to access the application by entering the IP address of the server when I'm on that network.
该应用程序将在本地托管(而不是面向www)。将无法解析“www.domain.com”名称的DNS。我想通过在该网络上输入服务器的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? 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. That's why I tried setting the alias to /test
but that didn't work either.
我是否还需要将我的.wsgi文件保存在/ var / www / html目录中?或者他们可以进入不同的文件夹?我可以看到我发送到服务器的消息('Hello')和已经在/ var / www / html /目录中的静态文件之间可能存在一些冲突。这就是为什么我尝试将别名设置为/ 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能够提供所有静态文件。
1 个解决方案
#1
9
Fixing the 500 errors
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). Change your handler to:
您当前获得500个错误,因为您的处理程序是一个基本的WSGI处理程序,但Flask处理程序不是WSGI处理程序(Flask / Werkzeug为您提取所有这些内容)。将处理程序更改为:
@app.route("/")
def hello():
return "Hello"
and the 500 errors should go away.
并且500错误应该消失。
Serving static files with 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
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
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
. Quoting from the linked docs:
正如Graham Dumpleton在评论中指出的那样,当且仅当DocumentRoot中不存在文件时,您可以使用mod_rewrite将请求传递给Python。引用链接的文档:
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. 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:
使用AddHandler指令时,由脚本文件扩展名标识的WSGI应用程序,使WSGI应用程序显示为服务器根目录的唯一方法是使用mod_rewrite即时重写Apache内部的URL。 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'. 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. As this would probably be undesirable, many web frameworks provide an option to override what the value for the mount point is. 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.
但请注意,当为请求执行WSGI应用程序时,“SCRIPT_NAME”变量指示应用程序的挂载点将是“/site.wsgi”。这意味着当WSGI应用程序构建基于“SCRIPT_NAME”的绝对URL时,它将在URL中包含“site.wsgi”而不是隐藏它。由于这可能是不合需要的,因此许多Web框架提供了覆盖挂载点值的选项。如果没有这样的配置选项,那么在'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中,只要它不包含在第一位,并且该访问总是通过网站的根目录而不是。
#1
9
Fixing the 500 errors
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). Change your handler to:
您当前获得500个错误,因为您的处理程序是一个基本的WSGI处理程序,但Flask处理程序不是WSGI处理程序(Flask / Werkzeug为您提取所有这些内容)。将处理程序更改为:
@app.route("/")
def hello():
return "Hello"
and the 500 errors should go away.
并且500错误应该消失。
Serving static files with 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
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
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
. Quoting from the linked docs:
正如Graham Dumpleton在评论中指出的那样,当且仅当DocumentRoot中不存在文件时,您可以使用mod_rewrite将请求传递给Python。引用链接的文档:
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. 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:
使用AddHandler指令时,由脚本文件扩展名标识的WSGI应用程序,使WSGI应用程序显示为服务器根目录的唯一方法是使用mod_rewrite即时重写Apache内部的URL。 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'. 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. As this would probably be undesirable, many web frameworks provide an option to override what the value for the mount point is. 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.
但请注意,当为请求执行WSGI应用程序时,“SCRIPT_NAME”变量指示应用程序的挂载点将是“/site.wsgi”。这意味着当WSGI应用程序构建基于“SCRIPT_NAME”的绝对URL时,它将在URL中包含“site.wsgi”而不是隐藏它。由于这可能是不合需要的,因此许多Web框架提供了覆盖挂载点值的选项。如果没有这样的配置选项,那么在'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中,只要它不包含在第一位,并且该访问总是通过网站的根目录而不是。