调试 Apache/Django/WSGI 错误请求 (400) 错误

Posted

技术标签:

【中文标题】调试 Apache/Django/WSGI 错误请求 (400) 错误【英文标题】:Debugging Apache/Django/WSGI Bad Request (400) Error 【发布时间】:2013-12-17 18:29:00 【问题描述】:

我的简单 Django 应用程序在调试模式 (manage.py runserver) 下运行良好,并且在我的开发盒上的 WSGI+Apache 下运行,但是当我推送到 EC2 时,我开始收到间歇性(10-80% 的时间)错误Bad Request (400) 用于我尝试查看的任何 URL(无论是在我的应用程序中还是在 Django 管理员中。

在哪里可以找到有关此的调试信息? /var/log/apache2/error.log 中没有任何内容,即使是 LogLevel=info。我检查了版本,记录了请求环境(参见ModWSGI Debugging Tips),没有发现重大差异。

我剩下的一个想法是,我正在使用基于 Python 2.7.1 构建的 Ubuntu 12.04 (libapache2-mod-wsgi 3.3-4build1) 的 mod_wsgi;我有 Python 2.7.3。而 Django 是 1.6,比 Ubuntu Precise 版本更新。我犹豫是否开始从源代码构建软件包,因为清理起来非常困难,而且这些看起来像是次要的版本更改......

感谢您的帮助。

(供参考,这里是 Apache 配置和 WSGI 应用)

Apache 配置(000-默认)

<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www
    WSGIScriptAlias /rz /usr/local/share/rz/rz.wsgi
    ...

rz.WSGI 应用程序

import os
import sys
import django.core.handlers.wsgi
import pprint

path = '/usr/local/share/rz'
if path not in sys.path:
    sys.path.insert(0, path)

os.environ['DJANGO_SETTINGS_MODULE'] = 'rz.settings'

class LoggingMiddleware:
    def __init__(self, application):
        self.__application = application

    def __call__(self, environ, start_response):
        errors = environ['wsgi.errors']
        pprint.pprint(('REQUEST', environ), stream=errors)

        def _start_response(status, headers, *args):
            pprint.pprint(('RESPONSE', status, headers), stream=errors)
            return start_response(status, headers, *args)

        return self.__application(environ, _start_response)

application = LoggingMiddleware(django.core.handlers.wsgi.WSGIHandler())

【问题讨论】:

在 django 设置文件中设置 DEBUG = FALSE。并尝试重新启动 apache 服务器。 为什么 DEBUG=FALSE 让它更可靠?我已尝试重新启动,但没有看到任何改善。 ALLOW_HOSTS 设置是否正确?如果设置不正确,Django 将仅在 prod 模式下回复错误请求。如果它在部分时间正常工作 - 可能客户端通过不同的主机名连接,则 ALLOW_HOSTS 中可能缺少其中一些主机名。 是的,你明白了!谢谢,这是因为生产模式需要该设置。想知道为什么它是间歇性的,虽然...... 我在一个工作的虚拟服务器上做了一个sudo apt-get updatesudo apt-get upgrade,然后得到了 400 BAD REQUEST。它让我看到了这篇文章,解决方案是添加 ALLOWED_HOSTS。我认为这是因为升级更改为 Django 1.5 或更高版本。注意the "Important" comment here:“默认情况下,Django 1.3.6 和 1.4.4 设置 ALLOWED_HOSTS 以允许所有主机。这意味着要真正修复安全漏洞,您应该在升级后立即自行定义此设置。” 【参考方案1】:

像这样将 ALLOWED_HOSTS 设置添加到您的 settings.py...

ALLOWED_HOSTS = [
    '.example.com', # Allow domain and subdomains
    '.example.com.', # Also allow FQDN and subdomains
]

我遇到了同样的问题,找到了答案here in the docs

更新:django 1.6 文档不再在线,我更新了指向 django 1.7 文档ALLOWED_HOSTS 设置的链接。

【讨论】:

奇怪的东西。此解决方案仅适用于我的本地主机。当我尝试将my_site.com 添加到 ALLOWED_HOSTS(/etc/hosts 中的127.0.0.1 my_site.com)错误请求(400)再次出现。怎么了? @Anton 你的DEBUG 设置是什么?当您通过“my_site.com”访问您的网站时,是否有一个设置正在改变DEBUG 的值?它们可能是您的ALLOWED_HOSTS 设置中的错字吗?我需要更多信息 :) 我的猜测是您的 ALLOWED_HOSTS 设置中有错字,当您尝试通过“127.0.0.1”访问您的网站时它会被忽略,因为这会将 DEBUG 设置为 False。当您尝试通过“my_site.com”访问该站点时,您的 DEBUG 设置为 True 并使用具有类型的 ALLOWED_HOSTS。你有“.my_site.com”还是“mysite.com”? DEBUG 设置为 False。我创建了一个新的干净项目进行测试,所以没有什么可以改变 DEBUG 的值(至少我希望如此)。我尝试了很多 ALLOWED_HOSTS 的变体:ALLOWED_HOSTS = ['localhost', 'my_site.com', 'ubuntu-virtualbox']。 localhost 和 ubuntu-virtualbox -> 有效,my_site.com -> 错误请求,然后我尝试为所有主机提供访问权限:ALLOWED_HOSTS = ['*'],结果相同。即使我将 DEBUG 更改为 True,也只有 localhost 和 ubuntu-virtualbox 可用。 my_site.com 仍然返回 Bad Request 可能是因为 virtualenv 或某些系统设置? 这是我的问题***.com/questions/25357744/django-and-bad-request-400。我可以在那里提供更多信息。在 cmets 中发布代码太难了。 没有在 ALLOWED_HOSTS 中列出的站点也是我的问题。不过,我确实需要在更改后重新启动 Apache。没有重新启动 Apache,它继续显示偶尔的 http 400 错误请求。【参考方案2】:

如果您确定设置了ALOWED_HOSTS - 请确保您的主机名不包含下划线。这在技术上是非法的。

我不得不打印出各种函数,归结为这个正则表达式未能检测到 django.http 中的域

host_validation_re = re.compile(r"^([a-z0-9.-]+|\[[a-f0-9]*:[a-f0-9:]+\])(:\d+)?$")

确实,我的域中有一个下划线。

【讨论】:

Bingo - 经过 45 分钟的追捕,您的答案突出显示,果然,我在生产域(主机文件)中有一个下划线,但在开发域中没有。使用 DEBUG=False 很难调试。【参考方案3】:

不是解决方案,但出于调试目的,您可以像这样在 settings.py 中设置 ALLOWED_HOSTS 设置

ALLOWED_HOSTS = ['*']

它肯定可以工作。如果没有,至少你会知道问题不是 Django 拒绝访问给定的 url。

【讨论】:

这样做会禁用此变量打算设置的安全性。 @Mibou 即使使用此设置,当从一台服务器重定向到另一台服务器时,我的请求也很糟糕...... 这有利于调试原因,以确定问题是否与 ALOWED_HOSTS 相关。

以上是关于调试 Apache/Django/WSGI 错误请求 (400) 错误的主要内容,如果未能解决你的问题,请参考以下文章

Apache+Django++mod_wsgi(ubuntu下虚拟机方式部署过程)

无法使用 Visual Studio 2013 调试托管代码(“无法评估表达式”错误 - 正在使用调试版本)(请注意,VS 2012 有效)

支付宝支付接口​调试错误,请回到请求来源地,重新发起请求 错误代码 ILLEGAL_SIGN

PHP框架ThinkPHP关闭调试模式APP_DEBUG,出现页面错误,请稍后再试。

WCF调试错误:添加服务失败。服务元数据可能无法访问。请确保服务正在运行并且正在公开元数据。

调试错误,请回到请求来源地,重新发起请求。 错误代码 insufficient-isv-permissions 错误原因: ISV权限不足,建议在开发者中心检查对应功能是否已经添加