Ticket #444 (defect)
Opened 3 years ago
Last modified 3 years ago
CherryPy wsgiApp doesn't respect SCRIPT_NAME & PATH_INFO
Status: closed (invalid)
| Reported by: | ianb@colorstudy.com | Assigned to: | rdelon |
|---|---|---|---|
| Priority: | normal | Milestone: | |
| Component: | CherryPy code | Keywords: | |
| Cc: |
CherryPy doesn't respect the distinction between SCRIPT_NAME and PATH_INFO when running through the wsgiApp. SCRIPT_NAME and PATH_INFO are specified in the WSGI spec, and so wsgiApp must parse PATH_INFO and treat SCRIPT_NAME as only the path used to get *to* CherryPy. If any filters need to be set up, wsgiApp needs to set them up, it isn't the responsibility of the CherryPy application or the WSGI server to do this.
Really _cpwsgi.requestLine shouldn't just be rebuilding the request line, as it loses this context in the process. Or if it does, it should pass SCRIPT_NAME through other channels so that the URL parser can immediately strip SCRIPT_NAME and not use it to find the object.
Change History
01/20/06 03:04:55: Modified by fumanchu
- status changed from new to closed.
- resolution set to wontfix.
01/20/06 11:24:09: Modified by ianb@colorstudy.com
- status changed from closed to reopened.
- resolution deleted.
- summary changed from CherryPy doesn't respect SCRIPT_NAME & PATH_INFO to CherryPy wsgiApp doesn't respect SCRIPT_NAME & PATH_INFO.
- wsgiApp is a WSGI application. This is its role. If it is wrapping an HTTP framework, then it should do so correctly.
- The WSGI spec indicates the meaning of SCRIPT_NAME and PATH_INFO. It is the WSGI server's responsibility to make these correct. mod_python is not an WSGI server. There are WSGI servers built on mod_python -- if one doesn't set SCRIPT_NAME and PATH_INFO properly then it should be fixed.
- In some cases you may want to attach an unfixable server to CherryPy, and so you may have to change SCRIPT_NAME and PATH_INFO. But CherryPy/wsgiApp should assume that the values are correct barring other configuration.
I really don't understand the resistence. This is what the WSGI spec says, it isn't something unique to Paste, it's something that any WSGI consumer is likely to need. If CherryPy supported this properly then hacks like VirtualPathFilter wouldn't be necessary, the whole thing could be handled natively. But even putting that aside, wsgiApp is a WSGI application, and should act like it, regardless of what is right for CherryPy-the-HTTP-server. And none of this requires a radical reworking of CherryPy to fix.
01/20/06 21:44:13: Modified by fumanchu
...none of this requires a radical reworking of CherryPy to fix
Then I must be misunderstanding what you're asking for. We seem to be at an impasse philosophically, so if this is truly "not radical" then you should either: 1) provide a patch which shows more clearly what you intend, or 2) an example of a CP app which breaks because "wsgiApp doesn't respect SCRIPT_NAME".
01/21/06 19:27:46: Modified by ianb@colorstudy.com
- severity changed from major to normal.
If I mount, say, Catwalk on "/catwalk/" in Paste, that means that wsgiApp will be called with a WSGI environment where SCRIPT_NAME is "/catwalk" and the PATH_INFO is "/". At this point, CherryPy/wsgiApp should try to get the "/" object; instead it tries to get "/catwalk/", which doesn't exist, and I get a 404.
I have a test in CherryPaste/tests/test_script_name.py: http://svn.pythonpaste.org/Paste/CherryPaste/trunk/tests/test_script_name.py
This test passes now because I've hacked around this CherryPy bug in CherryPaste?. But it's getting really tiring to fix CherryPy's bugs from the outside.
01/21/06 20:55:20: Modified by fumanchu
- status changed from reopened to closed.
- resolution set to invalid.
At this point, CherryPy/wsgiApp should try to get the "/" object; instead it tries to get "/catwalk/", which doesn't exist, and I get a 404.
Then that's your fault as a CP app developer--you've written a broken app. The "/ object" which responds to SCRIPT_NAME = "/catwalk" and PATH_INFO = "/" does not have to be cherrypy.root.index. It's perfectly simple to provide such a handler; you can either construct it manually:
class CatwalkRoot(): def index(self): return "Welcome to catwalk" index.exposed = True cherrypy.root.catwalk = CatwalkRoot()
...or you can use the new cherrypy.tree.mount(CatwalkRoot(), "/catwalk") syntax in the 2.2 trunk, which does the same thing.
02/15/06 21:49:27: Modified by 贸易公司
- cc changed from ianb@colorstudy.com to 贸易公司.
- keywords changed from wsgi to 贸易公司.
- summary changed from CherryPy wsgiApp doesn't respect SCRIPT_NAME & PATH_INFO to 贸易公司.
03/08/06 06:11:52: Modified by dowski
- cc deleted.
- keywords deleted.
- summary changed from 注册香港公司I协会商会|出版社(香港瑞丰机构) to CherryPy wsgiApp doesn't respect SCRIPT_NAME & PATH_INFO.


First, CherryPy must work with servers and gateways that do not work like Paste; that is, they don't necessarily know where the "root" of the "application" is. Apache via modpython, for example, tends to set PATH_INFO to the last atom of the URL, and SCRIPT_NAME to the rest of the path. To assume a rigid interpretation of two tiny lines in the WSGI spec on this matter would render the spec practically useless, in effect requiring that all deployments use Paste (or something similar), or that all WSGI servers be designed to predict the internal dispatch mechanisms of all potential WSGI applications/frameworks. The fact that Paste itself exists and rewrites SCRIPT_NAME proves that any given interpretation of SCRIPT_NAME (even if in the spec) is neither canonical nor universal. That is, if we agree that CherryPy doesn't "respect" SCRIPT_NAME then we must immediately agree that Paste doesn't either, since it may rewrite the SCRIPT_NAME which is handed to it by the WSGI server. The spec itself would be better off IMO if SCRIPT_NAME were not blessed in this way, and in fact, seems to contradict itself when it says later that "[t]his specification does not define how a server selects or obtains an application to invoke. These and other configuration options are highly server-specific matters. It is expected that server/gateway authors will document how to configure the server to execute a particular application object, and with what options (such as threading options)" (emphasis mine).
Second, since CherryPy is an HTTP framework, and not a web application framework per se, it is very interested in rebuilding the request line. Since it must function with WSGI and without, it cannot assume that the WSGI interpretation of SCRIPT_NAME holds for all requests; therefore, SCRIPT_NAME is both a necessary component in responding to requests and "is some leading part of the <path> component of the Script-URI derived in some implementation defined manner". Since CherryPy is more than "a WSGI application", it has chosen to leave the interpretation of "implementation defined manner" to the developer of a CP app. Deployments which wish to have access to SCRIPT_NAME should add that entry to _cpwsgi.headerNames, and read the value from request.headers when needed.
Third, WSGI is an interface specification, not a recipe for building frameworks or applications. CherryPy "must invoke the start_response() callable" and "must return an iterable yielding zero or more strings" and not much else. Once you assume the spec dictates how CP should use environ variables in order to yield those strings, it is no longer an interface spec. Other tools (like Paste) can try to make those demands, but this ticket should be renamed and reworded if that's the case.
Finally, the ticket description uses the word "filter" in a way that CherryPy doesn't, so it's hard to parse. But my guess is that the phrase "wsgiApp needs to set them up" arises from the incorrect assumption that CherryPy is some sort of "WSGI application", which it isn't. It provides a WSGI interface, but it is more properly "an HTTP framework". Any functionality which CherryPy provides (beyond I/O-transformations for the WSGI interface) must be available regardless of whether the deployment uses the WSGI interface or not; therefore, whatever "filters" are, they are properly the responsibility of the CherryPy framework.