Django 1.11 onpassenger_wsgi 不路由 POST 请求 [英] Django 1.11 on passenger_wsgi not routing POST request

查看:47
本文介绍了Django 1.11 onpassenger_wsgi 不路由 POST 请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过passenger_wsgi 在A2 共享主机上设置python.当我通过runserver"运行该应用程序时,它运行良好.我在本地 PC 和 SSH 隧道中对此进行了测试.

但是,当我尝试在passenger_wsgi 上进行设置时,它似乎无法路由POST 请求.

 1 导入操作系统2 导入系统34 sys.path.insert(0, "/home/<用户名>/app")56 导入 APP_CORE78 # python解释器在哪里9 INTERP = "/home/<用户名>/app/.virtualenv/bin/python"10 如果 sys.executable != INTERP: os.execl(INTERP, INTERP, *sys.argv)111213 os.environ['DJANGO_SETTINGS_MODULE'] = "APP_CORE.settings"1415 导入APP_CORE.wsgi16 应用程序 = APP_CORE.wsgi.application

示例:当我加载管理页面 (/admin/login) 时,它可以加载登录页面,但是在提交凭据时,它说找不到 POST 到/admin/login - 返回 HTTP 404.

当我通过 runserver 运行时,相同的流程可以工作 - 我觉得我可能在 django WSGI 配置中遗漏了一些东西.任何帮助将不胜感激!

编辑/更新:在深入研究 resolver.py 和 base.py:_get_response 之后,我注意到/path/info 以某种方式截断了 URL 的第一位.例如,当我请求/admin/login/时,路径信息仅显示/login - 但是当我使用 runserver 时,它正确地作为/admin/login 传递.对我来说,这显然是 Web 服务器设置上的问题,而不是 django 站点上的问题.所以会尝试用 A2Hosting 解决这个问题...

解决方案

看起来您可能已经解决了这个问题,但是对于可能在这里绊倒的任何人,请继续跟进.我一直在使用带有 django(和 wagtail)的 A2Hosting、Passenger 和 CPanel.我发现在 POST 请求期间 wsgi SCRIPT_NAME 被设置为相对路径,而不是应用程序的根目录.

当我向每个应用程序调用添加日志记录时,正确的 GET 请求是:

<代码>{'REQUEST_URI': '/admin/','PATH_INFO': '/admin/','SCRIPT_NAME': '','请求参数': '','REQUEST_METHOD': 'GET',...

但在该页面上,表单提交了 POST,其中 PATH_INFO 设置不正确:

<代码>{'REQUEST_URI': '/admin/login/','PATH_INFO': '/登录/','SCRIPT_NAME': '/admin','请求参数': '','REQUEST_METHOD': 'POST',...

我最终使用的解决方法是创建中间件,该中间件断言已知的 SCRIPT_NAME 并从中重建 PATH_INFO.

# 将此设置为您的根SCRIPT_NAME = ''类PassengerPathInfoFix(对象):"""从 REQUEST_URI 设置 PATH_INFO,因为乘客不提供它."""def __init__(self, app):self.app = appdef __call __(自我,环境,start_response):从 urllib.parse 导入取消引用环境['SCRIPT_NAME'] = SCRIPT_NAMErequest_uri = unquote(环境['REQUEST_URI'])script_name = unquote(environ.get('SCRIPT_NAME', ''))offset = request_uri.startswith(script_name) 和 len(environ['SCRIPT_NAME']) 或 0环境['PATH_INFO'] = request_uri[offset:].split('?', 1)[0]返回 self.app(environ, start_response)应用程序 = get_wsgi_application()应用程序=PassengerPathInfoFix(应用程序)

相关阅读:

I'm trying to setup python on A2 shared hosting via passenger_wsgi. The app is working fine when I run it via 'runserver'. I tested this both in my local PC, and via SSH tunnel.

However, when I try to set this up on passenger_wsgi, it can't seem to be able to route POST request.

  1 import os
  2 import sys
  3 
  4 sys.path.insert(0, "/home/<username>/app")
  5 
  6 import APP_CORE
  7 
  8 # where is the python interpreter
  9 INTERP = "/home/<username>/app/.virtualenv/bin/python"
 10 if sys.executable != INTERP: os.execl(INTERP, INTERP, *sys.argv)
 11 
 12 
 13 os.environ['DJANGO_SETTINGS_MODULE'] = "APP_CORE.settings"
 14 
 15 import APP_CORE.wsgi
 16 application = APP_CORE.wsgi.application

Example: when I load the admin page (/admin/login), it can load the login page, but when submitting the credentials, it says that POST to /admin/login is not found - returning HTTP 404.

The SAME flow when I run via runserver works - I feel that I could be missing something in the django WSGI configuration. Any help would be appreciated !!

Edit/update: After diving into resolver.py and base.py:_get_response, I've noticed that somehow the /path/info truncates the first bit of the URL. Example, when I am requesting for /admin/login/, the path info only shows /login - but when I am using runserver, it is properly passed thru as /admin/login. To me this is clearly the issue on the web server setup and not on the django site. So will try to work it out with A2Hosting...

解决方案

It looks like you may have solved this, but to followup for anyone that may stumble here. I have been using A2Hosting, Passenger, and CPanel with django (and wagtail). What I found was that during POST requests the wsgi SCRIPT_NAME was being set to a relative path and not the root of the application.

When I added logging to each application call, the correct GET request was:

{
  'REQUEST_URI': '/admin/',
  'PATH_INFO': '/admin/',
  'SCRIPT_NAME': '',
  'QUERY_STRING': '',
  'REQUEST_METHOD': 'GET',
  ...

But on that page, a form was submitting a POST, which had the PATH_INFO incorrectly set:

{
  'REQUEST_URI': '/admin/login/',
  'PATH_INFO': '/login/',
  'SCRIPT_NAME': '/admin',
  'QUERY_STRING': '',
  'REQUEST_METHOD': 'POST',
  ...

The workaround I ended up using was to create middleware which asserted a known SCRIPT_NAME and rebuilt the PATH_INFO from it.

# Set this to your root
SCRIPT_NAME = ''

class PassengerPathInfoFix(object):
    """
    Sets PATH_INFO from REQUEST_URI since Passenger doesn't provide it.
    """
    def __init__(self, app):
        self.app = app

    def __call__(self, environ, start_response):
        from urllib.parse import unquote
        environ['SCRIPT_NAME'] = SCRIPT_NAME

        request_uri = unquote(environ['REQUEST_URI'])
        script_name = unquote(environ.get('SCRIPT_NAME', ''))
        offset = request_uri.startswith(script_name) and len(environ['SCRIPT_NAME']) or 0
        environ['PATH_INFO'] = request_uri[offset:].split('?', 1)[0]
        return self.app(environ, start_response)


application = get_wsgi_application()
application = PassengerPathInfoFix(application)

Related Reading:

这篇关于Django 1.11 onpassenger_wsgi 不路由 POST 请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆