pallets / flask

The Python micro framework for building web applications.
https://flask.palletsprojects.com
BSD 3-Clause "New" or "Revised" License
67.71k stars 16.17k forks source link

Exception when trying to run Flask app via CGIHandler #857

Closed homeworkprod closed 10 years ago

homeworkprod commented 11 years ago

I have a very simple app. It runs fine when the module (itself calling app.run()) is run.

However, when I try to run the app via CGI on Apache 2 using this .cgi script:

#!/usr/bin/env python

from wsgiref.handlers import CGIHandler
from someapp import app

CGIHandler().run(app)

it results in an exception:

Traceback (most recent call last):
  File "/usr/lib/python2.7/wsgiref/handlers.py", line 85, in run
    self.result = application(self.environ, self.start_response)
  File "/home/user/projects/SomeProject/venv/lib/python2.7/site-packages/flask/app.py", line 1836, in __call__
    return self.wsgi_app(environ, start_response)
  File "/home/user/projects/SomeProject/venv/lib/python2.7/site-packages/flask/app.py", line 1812, in wsgi_app
    ctx = self.request_context(environ)
  File "/home/user/projects/SomeProject/venv/lib/python2.7/site-packages/flask/app.py", line 1773, in request_context
    return RequestContext(self, environ)
  File "/home/user/projects/SomeProject/venv/lib/python2.7/site-packages/flask/ctx.py", line 247, in __init__
    self.match_request()
  File "/home/user/projects/SomeProject/venv/lib/python2.7/site-packages/flask/ctx.py", line 286, in match_request
    self.url_adapter.match(return_rule=True)
  File "/home/user/projects/SomeProject/venv/lib/python2.7/site-packages/werkzeug/routing.py", line 1386, in match
    self.subdomain, path_info.lstrip('/'))
AttributeError: 'NoneType' object has no attribute 'lstrip'

The setup is Flask 0.10.1 with Werkzeug 0.9.4.

On first sight, the WSGI environment variables seem to be incomplete, or something like that.

pradloff commented 11 years ago

I too am seeing this, I'm trying to track down what is causing the problem. Here is some information I've managed to get. My .htaccess appears below and is followed by server information and the traceback. The recommended routing in the flask documentation returned 500, this was what I found to work. I'm keeping open the possibility of a server configuration problem as well. I've removed what I feel to be personal information including my username, server name, server address, and admin email.

RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /USERNAME/cgi-bin/run3.cgi [L,QSA]

Error in application running An error occured here are some diagnostics: wsgi.multiprocess: True REDIRECT_STATUS: 200 SERVER_SOFTWARE: Apache/2.2.15 (Red Hat) DAV/2 SCRIPT_NAME: /~USERNAME/cgi-bin/run3.cgi SERVER_SIGNATURE:

Apache/2.2.15 (Red Hat) DAV/2 Server at SERVERNAME Port 80

REQUEST_METHOD: GET REDIRECT_URL: /~USERNAME/hello SERVER_PROTOCOL: HTTP/1.1 QUERY_STRING: PATH: /usr/local/bin:/usr/bin:/bin HTTP_USER_AGENT: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.76 Safari/537.36 HTTP_CONNECTION: keep-alive SERVER_NAME: SERVER_NAME REMOTE_PORT: 50347 wsgi.url_scheme: http SERVER_PORT: 80 SERVER_ADDR: SERVER_ADDR DOCUMENT_ROOT: /var/empty SCRIPT_FILENAME: /home1/USERNAME/public_html/cgi-bin/run3.cgi SERVER_ADMIN: SERVER_ADMIN SCRIPT_URI: http://SERVERNAME/USERNAME/hello wsgi.input: <open file '', mode 'r' at 0x7f33e6e420c0> HTTP_HOST: SERVER_NAME SCRIPT_URL: /USERNAME/hello wsgi.multithread: False HTTP_CACHE_CONTROL: max-age=0 REQUEST_URI: /USERNAME/hello HTTPACCEPT: text/html,application/xhtml+xml,application/xml;q=0.9,/_;q=0.8 wsgi.version: (1, 0) GATEWAY_INTERFACE: CGI/1.1 wsgi.run_once: True wsgi.errors: <open file '', mode 'w' at 0x7f33e6e421e0> REMOTE_ADDR: 128.223.131.46 HTTP_ACCEPT_LANGUAGE: en-US,en;q=0.8 wsgi.file_wrapper: wsgiref.util.FileWrapper HTTP_ACCEPT_ENCODING: gzip,deflate,sdch

Exception occured: File "run3.cgi", line 22, in run cgihandler.result = application(cgihandler.environ, cgihandler.start_response) File "/home1/USERNAME/.local/lib/python2.6/site-packages/Flask-0.10.1-py2.6.egg/flask/app.py", line 1836, in call return self.wsgi_app(environ, start_response) File "/home1/USERNAME/.local/lib/python2.6/site-packages/Flask-0.10.1-py2.6.egg/flask/app.py", line 1812, in wsgi_app ctx = self.request_context(environ) File "/home1/USERNAME/.local/lib/python2.6/site-packages/Flask-0.10.1-py2.6.egg/flask/app.py", line 1773, in request_context return RequestContext(self, environ) File "/home1/USERNAME/.local/lib/python2.6/site-packages/Flask-0.10.1-py2.6.egg/flask/ctx.py", line 247, in init self.match_request() File "/home1/USERNAME/.local/lib/python2.6/site-packages/Flask-0.10.1-py2.6.egg/flask/ctx.py", line 286, in match_request self.url_adapter.match(return_rule=True) File "/home1/USERNAME/.local/lib/python2.6/site-packages/Werkzeug-0.9.4-py2.6.egg/werkzeug/routing.py", line 1386, in match self.subdomain, path_info.lstrip('/'))

AttributeError: 'NoneType' object has no attribute 'lstrip'

pradloff commented 11 years ago

Well, I've played around some more and seem to have got a working configuration.

My .htaccess file looks like:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f                                   
RewriteRule ^(.*)$ /USERNAME/cgi-bin/run3.cgi/$1 [L]

This is the same as the flask recommendation http://flask.pocoo.org/docs/deploying/cgi/, except I've removed the comment on the second line. I'm not sure if that was the intention of the documentation to have an actual comment in the .htaccess file. It appears the sketchy workaround I found was causing the actual problem with flask.

I cannot tell you if the initiator of this bug followed a similar path to cause the bug.

Cheers,

prad

ThiefMaster commented 11 years ago

(You know that using CGI is a bad idea, right?)

pradloff commented 11 years ago

I'm aware that it is very limited, but it is the only option on the server we are provided.

homeworkprod commented 11 years ago

pradloff: I'll fiddle around with my Apache config and see what happens. But I definitely had no line in it with a trailing line comment.

ThiefMaster: I disagree. It's often the only way to run Python on common PHP/MySQL-class hostings, and it's a good choice for self-hosting many tiny, seldomly accessed apps for which one doesn't want to have processes lurking around and supervisors to be configured. If you want to discuss this further, I'm happy to do that on IRC; let's get back to the topic here.

homeworkprod commented 11 years ago

OK, just a bit more background: I wrote a bunch of CGI scripts and want to make them WSGI-compatible so they can be served "in a modern fashion". But not being able to actually run the new versions with CGI (via WSGI) would keep the existing users that want/need CGI from updating.

In this state, i. e. ported to Flask, but unable to be run via GCI, I'm kept from releasing the new versions.

untitaker commented 11 years ago

Bug introduced in https://github.com/mitsuhiko/werkzeug/commit/daad95172be601175777ecacad34be0083188fcf#L0L1231

johanneskoester commented 10 years ago

If you add a trailing slash to the url, it works for me. What about the pull request? Did it solve the issue, and why was it rejected?

Thanks a lot for your help, Johannes

untitaker commented 10 years ago

No idea. I pinged @mitsuhiko about this in IRC.

johanneskoester commented 10 years ago

I tested it myself. It seems to be sufficient to use the first part of your pull request.

untitaker commented 10 years ago

Yes, the second part are just tests that fail unless the first part is applied.

mitsuhiko commented 10 years ago

This is a bug in the CGI handler. PATH_INFO must not be None.

mitsuhiko commented 10 years ago

To fix this use a middleware that fixes up the issue. See https://github.com/mitsuhiko/werkzeug/pull/440