Ticket #638 (defect)
Opened 2 years ago
Last modified 2 years ago
Cannot mount two CP apps using PasteDeploy
Status: closed (fixed)
| Reported by: | alberto@toscat.net | Assigned to: | rdelon |
|---|---|---|---|
| Priority: | normal | Milestone: | |
| Component: | CherryPy code | Keywords: | |
| Cc: |
Hi,
I've downloaded the zip file found at http://cherrypy.org/wiki/CherryPyAndPasteCanPlayNice but I'm having problems mounting the same blogapp at different urls using URLMap.
My configuration file looks like this:
[composite:main] use = egg:Paste#urlmap / = blogapp0 /blog1 = blogapp1 /blog2= blogapp2 [app:blogapp0] use = egg:cp_blog_app#main bar = Im blog 0 [app:blogapp1] use = egg:cp_blog_app#main bar = Im blog 1 [app:blogapp2] use = egg:cp_blog_app#main bar = Im blog 2 [server:main] use = egg:Paste#http host = 127.0.0.1 port = 8080
The problems I see are:
- /blog1 and /blog2 causes "303 See other" redirect loops.
- /blog1/foo returns "im blog 0" (should be "im blog 1" as specified by config)
- /blog2/foo returns "im blog 0" (should be "im blog 2")
I've been doing some experiements with this and made it work by monkey-patching cherrypy.config to use paste.deploy.config.CONFIG and stacking a paste.config.ConfigMiddleware above the CP app in the app_factory.
I could share some code if interested.
Alberto
Change History
01/07/07 22:04:41: Modified by alberto@toscat.net
01/07/07 22:22:58: Modified by fumanchu
Thanks for trying it out! I think the "Im blog X" problems are due to a small bug in the cpwsgihelper file. If I understand correctly, it should be the following instead:
def make_factory(app): """Return a PasteDeploy compatible app_factory that will configure the given Application. """ def app_factory(global_config, **local_conf): cherrypy.config.update(global_config) app.merge({'/': local_conf}) init_wsgi() return app return app_factory
Am I correct in thinking that the line bar = Im blog 1 should be passed in local_conf and not global_config?
01/07/07 23:08:48: Modified by alberto@toscat.net
Yep, it should be passed as local_conf. However, I've tried the app_factory "patch" and get the same results.
Code I mentioned is at http://paste.turbogears.org/paste/769 and http://paste.turbogears.org/paste/770
Some experimental code merging deployment config with app CP-style config (should enable setting up tools, etc... a là CherryPy) is at http://paste.turbogears.org/paste/783
paste.turbogears.org (paste for pastebin, any coincidence with the subject of the ticket purely coincindential! ;) should be online now.
Alberto
01/08/07 00:32:03: Modified by fumanchu
Aha. Then cp_blog_app shouldn't create the Application object, because that single global object is being re-used for each mounting. Instead, it should say app_factory = make_factory(BlogApp) and make_factory should look something like this:
def make_factory(root): """Return a PasteDeploy compatible app_factory that will configure the given Application root. """ def app_factory(global_config, **local_conf): cherrypy.config.update(global_config) app = cherrypy.Application(root(), script_name=None) app.merge({'/': local_conf}) init_wsgi() return app return app_factory
I think that will remove the need for any config hacks. And if you're using Paste to mount applications, there should be no need for Tree or any hacks to Tree.
01/08/07 08:19:56: Modified by alberto
yep! That made it work... :) So I grasp that a Tree is a full tree, I mean, should always be rooted at app's "/"(base_url aside...), right? No problem really as, like you've said, app's could be still be composed by Paste using CP's Application objects to wrap CP apps.
It would still be nice if those globals (I can think of request, response, config, engine?,.... am i missing something?) could be stacked so CP applications could act as middleware if needed. I'll be posting at our thread in the trunk ML the use cases we have for that soon. To give an advance, we'd like to be able to do:
class MyController(TGController): blog = WsgiApp(load_app("config:foo.ini"))
Where the app loaded could be a CP app. TG controllers should be completely agnostic of the fact that the app is a CP or not... (it might even be close-sourced!)
Thanks for the help,
Alberto
01/08/07 10:42:17: Modified by fumanchu
- status changed from new to closed.
- resolution set to fixed.
So I grasp that a Tree is a full tree, I mean, should always be rooted at app's "/"(base_url aside...), right? No problem really as, like you've said, app's could be still be composed by Paste using CP's Application objects to wrap CP apps.
I think I should say "yes", but there's an odd double-use of "app" in that statement, both for a WSGI component and a WSGI complex of WSGI components. It would be simpler for me to say "yes" if it said:
A Tree is a full tree, and should always be rooted at site's "/" (proxy urls aside...). But it doesn't have to be the first object in the WSGI stack--it's just that it uses SCRIPT_NAME to dispatch, and SCRIPT_NAME is always "rooted" at "/". No problem really as complexes could be still be composed by Paste using CP's Application objects to wrap CP apps.
In other words, we've got to find a new word for "set of apps working together" that's not the word "app". We could use "site", but that goes too far the other way, implying that all are mounted at "/" and directly connected to an HTTP server. A "complex" can be mounted anywhere; a Tree can appear anywhere in a WSGI stack; but SCRIPT_NAME is always an absolute URL.
01/08/07 11:23:27: Modified by fumanchu
I might not have said that bit about Tree and SCRIPT_NAME right. What I meant was that a Tree always uses SCRIPT_NAME to dispatch, and so it's never really "mounted" at a URL. It can appear anywhere in the WSGI stack and it will act the same way.
01/14/07 21:50:59: Modified by dowski
Updated the example at CherryPyAndPasteCanPlayNice based on this information. Thanks.


BTW, The redirect problems dissapear when I change server to use cherrypy (requires PasteScript==dev for 3.0.0)
Alberto