Merge lp:~salgado/launchpad/bug-535071 into lp:launchpad

Proposed by Guilherme Salgado
Status: Merged
Merged at revision: not available
Proposed branch: lp:~salgado/launchpad/bug-535071
Merge into: lp:launchpad
Diff against target: 118 lines (+58/-13)
3 files modified
lib/canonical/launchpad/browser/librarian.py (+22/-12)
lib/canonical/launchpad/browser/tests/test_librarian.py (+30/-0)
lib/canonical/librarian/client.py (+6/-1)
To merge this branch: bzr merge lp:~salgado/launchpad/bug-535071
Reviewer Review Type Date Requested Status
Björn Tillenius (community) Abstain
Gary Poster (community) Approve
Review via email: mp+22173@code.launchpad.net

Description of the change

StreamOrRedirectLibraryFileAliasView no longer OOPSes when trying to
stream a restricted file while the librarian is down.

Just catches the exception and return a text/plain error message. The
choice for text/plain as the content-type is because I don't think it'd
make sense to render a regular LP page with just an error message in
this case.

= Launchpad lint =

Checking for conflicts. and issues in doctests and templates.
Running jslint, xmllint, pyflakes, and pylint.
Using normal rules.

Linting changed files:
  lib/canonical/librarian/client.py
  lib/canonical/launchpad/browser/librarian.py
  lib/canonical/launchpad/browser/tests/test_librarian.py

== Pylint notices ==

lib/canonical/librarian/client.py
    27: [F0401] Unable to import 'zope.interface'

lib/canonical/launchpad/browser/librarian.py
    21: [F0401] Unable to import 'zope.interface'
    22: [F0401] Unable to import 'zope.publisher.interfaces'
    23: [F0401] Unable to import 'zope.publisher.interfaces.browser'
    24: [F0401] Unable to import 'zope.security.interfaces'
    38: [F0401] Unable to import 'lazr.delegates'

To post a comment you must log in.
Revision history for this message
Gary Poster (gary) wrote :

Thank you

Gary

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

Am I reading correctly, in that the status code is code 200? The test doesn't show, but I don't see the status code being set anywhere. What's the status code if the Librarian is down? Why?

review: Abstain
Revision history for this message
Guilherme Salgado (salgado) wrote :

Good catch; the status code in the response is still 200 (the default). I guess 503 would be the correct one in this case?

Revision history for this message
Gary Poster (gary) wrote :

Yes, thank you, Björn.

I agree, Salgado, 503 makes sense.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/canonical/launchpad/browser/librarian.py'
2--- lib/canonical/launchpad/browser/librarian.py 2009-11-24 15:36:44 +0000
3+++ lib/canonical/launchpad/browser/librarian.py 2010-03-26 14:07:32 +0000
4@@ -32,6 +32,7 @@
5 IWebBrowserOriginatingRequest)
6 from canonical.launchpad.webapp.url import urlappend
7 from canonical.lazr.utils import get_current_browser_request
8+from canonical.librarian.interfaces import LibrarianServerError
9 from canonical.librarian.utils import filechunks, guess_librarian_encoding
10
11 from lazr.delegates import delegates
12@@ -82,18 +83,7 @@
13
14 __used_for__ = ILibraryFileAlias
15
16- def __call__(self):
17- """Streams the contents of the context `ILibraryFileAlias`.
18-
19- The file content is downloaded in chunks directly to a
20- `tempfile.TemporaryFile` avoiding using large amount of memory.
21-
22- The temporary file is returned to the zope publishing machinery as
23- documented in lib/zope/publisher/httpresults.txt, after adjusting
24- the response 'Content-Type' appropriately.
25-
26- This method explicit ignores the local 'http_proxy' settings.
27- """
28+ def getFileContents(self):
29 # Reset system proxy setting if it exists. The urllib2 default
30 # opener is cached that's why it has to be re-installed after
31 # the shell environment changes. Download the library file
32@@ -113,6 +103,26 @@
33 if original_proxy is not None:
34 os.environ['http_proxy'] = original_proxy
35 urllib2.install_opener(urllib2.build_opener())
36+ return tmp_file
37+
38+ def __call__(self):
39+ """Streams the contents of the context `ILibraryFileAlias`.
40+
41+ The file content is downloaded in chunks directly to a
42+ `tempfile.TemporaryFile` avoiding using large amount of memory.
43+
44+ The temporary file is returned to the zope publishing machinery as
45+ documented in lib/zope/publisher/httpresults.txt, after adjusting
46+ the response 'Content-Type' appropriately.
47+
48+ This method explicit ignores the local 'http_proxy' settings.
49+ """
50+ try:
51+ tmp_file = self.getFileContents()
52+ except LibrarianServerError:
53+ self.request.response.setHeader('Content-Type', 'text/plain')
54+ return (u'There was a problem fetching the contents of this '
55+ 'file. Please try again in a few minutes.')
56
57 # XXX: Brad Crittenden 2007-12-05 bug=174204: When encodings are
58 # stored as part of a file's metadata this logic will be replaced.
59
60=== added file 'lib/canonical/launchpad/browser/tests/test_librarian.py'
61--- lib/canonical/launchpad/browser/tests/test_librarian.py 1970-01-01 00:00:00 +0000
62+++ lib/canonical/launchpad/browser/tests/test_librarian.py 2010-03-26 14:07:32 +0000
63@@ -0,0 +1,30 @@
64+# Copyright 2010 Canonical Ltd. All rights reserved.
65+
66+__metaclass__ = type
67+
68+__all__ = []
69+
70+from canonical.launchpad.browser.librarian import (
71+ StreamOrRedirectLibraryFileAliasView)
72+from canonical.launchpad.webapp.servers import LaunchpadTestRequest
73+from canonical.librarian.interfaces import LibrarianServerError
74+
75+from lp.testing import TestCase
76+
77+
78+class FakeRestrictedLibraryFileAlias:
79+ deleted = False
80+ restricted = True
81+
82+ def open(self):
83+ raise LibrarianServerError('Librarian is down')
84+
85+
86+class TestStreamOrRedirectLibraryFileAliasView(TestCase):
87+
88+ def test_restricted_file_when_librarian_is_down(self):
89+ view = StreamOrRedirectLibraryFileAliasView(
90+ FakeRestrictedLibraryFileAlias(), LaunchpadTestRequest())
91+ html = view()
92+ self.assertIn(
93+ 'There was a problem fetching the contents of this file', html)
94
95=== modified file 'lib/canonical/librarian/client.py'
96--- lib/canonical/librarian/client.py 2010-02-09 00:17:40 +0000
97+++ lib/canonical/librarian/client.py 2010-03-26 14:07:32 +0000
98@@ -159,7 +159,7 @@
99 id=contentID, filesize=size,
100 sha1=shaDigester.hexdigest(),
101 md5=md5Digester.hexdigest())
102- alias = LibraryFileAlias(
103+ LibraryFileAlias(
104 id=aliasID, content=content, filename=name.decode('UTF-8'),
105 mimetype=contentType, expires=expires,
106 restricted=self.restricted)
107@@ -356,6 +356,11 @@
108 if time.time() <= try_until:
109 time.sleep(1)
110 else:
111+ # There's a test (in
112+ # lib/c/l/browser/tests/test_librarian.py) which
113+ # simulates a librarian server error by raising this
114+ # exception, so if you change the exception raised
115+ # here, make sure you update the test.
116 raise LibrarianServerError(str(error))
117 else:
118 raise