Django 1.11 on passenger_wsgi not routing POST request

梦想与她 提交于 2019-12-13 00:33:44

问题


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...


回答1:


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:

  • http://alyalearningdjango.blogspot.com/2014/05/issue-360-passenger-doesnt-set-pathinfo.html
  • https://github.com/phusion/passenger/issues/460
  • https://www.python.org/dev/peps/pep-0333/#environ-variables


来源:https://stackoverflow.com/questions/49594955/django-1-11-on-passenger-wsgi-not-routing-post-request

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!