Merge lp:~bjornt/launchpad/bug-376990 into lp:launchpad/db-devel

Proposed by Björn Tillenius
Status: Merged
Approved by: Brad Crittenden
Approved revision: no longer in the source branch.
Merged at revision: not available
Proposed branch: lp:~bjornt/launchpad/bug-376990
Merge into: lp:launchpad/db-devel
Diff against target: None lines
To merge this branch: bzr merge lp:~bjornt/launchpad/bug-376990
Reviewer Review Type Date Requested Status
Brad Crittenden (community) mentor Approve
Leonard Richardson (community) Approve
Review via email: mp+9320@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Björn Tillenius (bjornt) wrote :

This branch makes canonical_url() produce browser URLs, even though the
current request is a web service request. We have some problems that API
URLs are used instead of browser URLs, for example in XHTML.
presentations and when e-mail notifications are generated inside API.
methods.

IMHO, canonical_url() should be split into two functions, but it's too.
late to do that now. I'd like one function that always returns a browser
URL, and one that returns either a browser or web service URL, depending
on which request is currently used. That's basically how I made.
canonical_url() work with this change. If no request is explicitly.
passed to it, a browser URL is always returned. In the case where you.
may want an API URL, you have to pass in the current request explicitly.
That's why I had to pass in the request to canonical_url() in the.
/people/foo rediretor, since it's used in both the app and web service
servers. Basically all code that redirects objects to canonical_url().
will need to pass in the request explicitly. At the moment all tests.
pass, but we might find a few bugs later. I don't expect this to be a.
big deal, though.

In this branch I also made canonical_url.txt run in FunctionalLayer, so
that it runs a bit faster.

BTW, I'm not going to land this branch before someone with more web.
service foo has commented on it, but I have discussed this approach with.
them already.

Revision history for this message
Leonard Richardson (leonardr) wrote :

Approved.*

review: Approve
Revision history for this message
Leonard Richardson (leonardr) wrote :

> Approved.*

I'm not totally happy with this solution, but there are so many call sites that changing the default behavior is the only real way to fix this.

Revision history for this message
Brad Crittenden (bac) wrote :

* line 11: s/want/wants
* line 13: typo: therefore
* The last sentence reads better as:
Therefore, if no request is explicitly given canonical_url() returns the browser
URL, even if the current request is a web service request.

Thanks for making the change to FunctionalLayer. Did you measure the improvement?

review: Approve (mentor)
Revision history for this message
Björn Tillenius (bjornt) wrote :

On Tue, Jul 28, 2009 at 01:13:29PM -0000, Brad Crittenden wrote:
> Review: Approve mentor
> * line 11: s/want/wants
> * line 13: typo: therefore

Why do I always make that typo? :)

> * The last sentence reads better as:
> Therefore, if no request is explicitly given canonical_url() returns the browser
> URL, even if the current request is a web service request.

Thanks, I'll fix it.

>
> Thanks for making the change to FunctionalLayer. Did you measure the
> improvement?

Yes. It's still quite slow, but took it down from 40 seconds to 20
seconds.

--
Björn Tillenius | https://launchpad.net/~bjornt

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/canonical/launchpad/doc/canonical_url.txt'
2--- lib/canonical/launchpad/doc/canonical_url.txt 2009-05-13 16:51:38 +0000
3+++ lib/canonical/launchpad/doc/canonical_url.txt 2009-07-27 13:45:52 +0000
4@@ -492,6 +492,37 @@
5 NoCanonicalUrl: No url for <...ObjectThatHasUrl...> because <...object...> broke the chain.
6
7
8+== canonical_url in the web service ==
9+
10+canonical_url() is sometimes used in code that doesn't have direct
11+access to the current request, and always want a URL that can be used in
12+a browser (for example e-mail notifications or XHTML representations of
13+objects). Therefor, if no request is explicitly given, and the current
14+request is a web service request, canonical_url() returns the browser
15+URL.
16+
17+ >>> from zope.app.security.principalregistry import (
18+ ... UnauthenticatedPrincipal)
19+ >>> from canonical.launchpad.webapp.servers import WebServiceTestRequest
20+ >>> from canonical.launchpad.webapp.interaction import setupInteraction
21+ >>> from lazr.restful.utils import get_current_browser_request
22+ >>> anonymous = UnauthenticatedPrincipal(None, None, None)
23+ >>> api_request = WebServiceTestRequest()
24+ >>> setupInteraction(anonymous, participation=api_request)
25+ >>> get_current_browser_request() is api_request
26+ True
27+
28+ >>> canonical_url(countryset_instance)
29+ u'http://launchpad.dev/countries'
30+
31+
32+If an URL that can be used in the web service is required, a web service
33+request has to be passed in explicitly.
34+
35+ >>> canonical_url(countryset_instance, request=api_request)
36+ u'http://api.launchpad.dev/countries'
37+
38+
39 == The end ==
40
41 We've finished with our interfaces and utility component, so remove them from
42
43=== modified file 'lib/canonical/launchpad/ftests/test_system_documentation.py'
44--- lib/canonical/launchpad/ftests/test_system_documentation.py 2009-07-17 00:26:05 +0000
45+++ lib/canonical/launchpad/ftests/test_system_documentation.py 2009-07-24 08:59:59 +0000
46@@ -273,6 +273,12 @@
47 tearDown=updateRemoteProductTeardown,
48 layer=LaunchpadZopelessLayer
49 ),
50+ 'canonical_url.txt': LayeredDocFileSuite(
51+ '../doc/canonical_url.txt',
52+ setUp=setUp,
53+ tearDown=tearDown,
54+ layer=FunctionalLayer,
55+ ),
56 }
57
58
59
60=== modified file 'lib/canonical/launchpad/webapp/publisher.py'
61--- lib/canonical/launchpad/webapp/publisher.py 2009-06-25 05:30:52 +0000
62+++ lib/canonical/launchpad/webapp/publisher.py 2009-07-24 12:52:33 +0000
63@@ -38,7 +38,7 @@
64 from zope.traversing.browser.interfaces import IAbsoluteURL
65
66 from canonical.cachedproperty import cachedproperty
67-from canonical.launchpad.layers import setFirstLayer
68+from canonical.launchpad.layers import setFirstLayer, WebServiceLayer
69 from canonical.launchpad.webapp.vhosts import allvhosts
70 from canonical.launchpad.webapp.interfaces import (
71 ICanonicalUrlData, ILaunchBag, ILaunchpadApplication, ILaunchpadContainer,
72@@ -463,6 +463,21 @@
73 # Look for a request from the interaction.
74 current_request = get_current_browser_request()
75 if current_request is not None:
76+ if WebServiceLayer.providedBy(current_request):
77+ from canonical.launchpad.webapp.publication import (
78+ LaunchpadBrowserPublication)
79+ from canonical.launchpad.webapp.servers import (
80+ LaunchpadBrowserRequest)
81+ current_request = LaunchpadBrowserRequest(
82+ current_request.bodyStream.getCacheStream(),
83+ dict(current_request.environment))
84+ current_request.setPublication(
85+ LaunchpadBrowserPublication(None))
86+ current_request.setVirtualHostRoot(names=[])
87+ main_root_url = current_request.getRootURL(
88+ 'mainsite')
89+ current_request._app_server = main_root_url.rstrip('/')
90+
91 request = current_request
92
93 if view_name is not None:
94
95=== modified file 'lib/lp/registry/browser/person.py'
96--- lib/lp/registry/browser/person.py 2009-07-20 15:27:26 +0000
97+++ lib/lp/registry/browser/person.py 2009-07-27 13:37:23 +0000
98@@ -616,14 +616,16 @@
99 if person is None:
100 raise NotFoundError(name)
101 # Redirect to /~name
102- return self.redirectSubTree(canonical_url(person))
103+ return self.redirectSubTree(
104+ canonical_url(person, request=self.request))
105
106 @stepto('+me')
107 def me(self):
108 me = getUtility(ILaunchBag).user
109 if me is None:
110 raise Unauthorized("You need to be logged in to view this URL.")
111- return self.redirectSubTree(canonical_url(me), status=303)
112+ return self.redirectSubTree(
113+ canonical_url(me, request=self.request), status=303)
114
115
116 class PersonSetContextMenu(ContextMenu):

Subscribers

People subscribed via source and target branches

to status/vote changes: