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
=== modified file 'lib/canonical/launchpad/browser/librarian.py'
--- lib/canonical/launchpad/browser/librarian.py 2009-11-24 15:36:44 +0000
+++ lib/canonical/launchpad/browser/librarian.py 2010-03-26 14:07:32 +0000
@@ -32,6 +32,7 @@
32 IWebBrowserOriginatingRequest)32 IWebBrowserOriginatingRequest)
33from canonical.launchpad.webapp.url import urlappend33from canonical.launchpad.webapp.url import urlappend
34from canonical.lazr.utils import get_current_browser_request34from canonical.lazr.utils import get_current_browser_request
35from canonical.librarian.interfaces import LibrarianServerError
35from canonical.librarian.utils import filechunks, guess_librarian_encoding36from canonical.librarian.utils import filechunks, guess_librarian_encoding
3637
37from lazr.delegates import delegates38from lazr.delegates import delegates
@@ -82,18 +83,7 @@
8283
83 __used_for__ = ILibraryFileAlias84 __used_for__ = ILibraryFileAlias
8485
85 def __call__(self):86 def getFileContents(self):
86 """Streams the contents of the context `ILibraryFileAlias`.
87
88 The file content is downloaded in chunks directly to a
89 `tempfile.TemporaryFile` avoiding using large amount of memory.
90
91 The temporary file is returned to the zope publishing machinery as
92 documented in lib/zope/publisher/httpresults.txt, after adjusting
93 the response 'Content-Type' appropriately.
94
95 This method explicit ignores the local 'http_proxy' settings.
96 """
97 # Reset system proxy setting if it exists. The urllib2 default87 # Reset system proxy setting if it exists. The urllib2 default
98 # opener is cached that's why it has to be re-installed after88 # opener is cached that's why it has to be re-installed after
99 # the shell environment changes. Download the library file89 # the shell environment changes. Download the library file
@@ -113,6 +103,26 @@
113 if original_proxy is not None:103 if original_proxy is not None:
114 os.environ['http_proxy'] = original_proxy104 os.environ['http_proxy'] = original_proxy
115 urllib2.install_opener(urllib2.build_opener())105 urllib2.install_opener(urllib2.build_opener())
106 return tmp_file
107
108 def __call__(self):
109 """Streams the contents of the context `ILibraryFileAlias`.
110
111 The file content is downloaded in chunks directly to a
112 `tempfile.TemporaryFile` avoiding using large amount of memory.
113
114 The temporary file is returned to the zope publishing machinery as
115 documented in lib/zope/publisher/httpresults.txt, after adjusting
116 the response 'Content-Type' appropriately.
117
118 This method explicit ignores the local 'http_proxy' settings.
119 """
120 try:
121 tmp_file = self.getFileContents()
122 except LibrarianServerError:
123 self.request.response.setHeader('Content-Type', 'text/plain')
124 return (u'There was a problem fetching the contents of this '
125 'file. Please try again in a few minutes.')
116126
117 # XXX: Brad Crittenden 2007-12-05 bug=174204: When encodings are127 # XXX: Brad Crittenden 2007-12-05 bug=174204: When encodings are
118 # stored as part of a file's metadata this logic will be replaced.128 # stored as part of a file's metadata this logic will be replaced.
119129
=== added file 'lib/canonical/launchpad/browser/tests/test_librarian.py'
--- lib/canonical/launchpad/browser/tests/test_librarian.py 1970-01-01 00:00:00 +0000
+++ lib/canonical/launchpad/browser/tests/test_librarian.py 2010-03-26 14:07:32 +0000
@@ -0,0 +1,30 @@
1# Copyright 2010 Canonical Ltd. All rights reserved.
2
3__metaclass__ = type
4
5__all__ = []
6
7from canonical.launchpad.browser.librarian import (
8 StreamOrRedirectLibraryFileAliasView)
9from canonical.launchpad.webapp.servers import LaunchpadTestRequest
10from canonical.librarian.interfaces import LibrarianServerError
11
12from lp.testing import TestCase
13
14
15class FakeRestrictedLibraryFileAlias:
16 deleted = False
17 restricted = True
18
19 def open(self):
20 raise LibrarianServerError('Librarian is down')
21
22
23class TestStreamOrRedirectLibraryFileAliasView(TestCase):
24
25 def test_restricted_file_when_librarian_is_down(self):
26 view = StreamOrRedirectLibraryFileAliasView(
27 FakeRestrictedLibraryFileAlias(), LaunchpadTestRequest())
28 html = view()
29 self.assertIn(
30 'There was a problem fetching the contents of this file', html)
031
=== modified file 'lib/canonical/librarian/client.py'
--- lib/canonical/librarian/client.py 2010-02-09 00:17:40 +0000
+++ lib/canonical/librarian/client.py 2010-03-26 14:07:32 +0000
@@ -159,7 +159,7 @@
159 id=contentID, filesize=size,159 id=contentID, filesize=size,
160 sha1=shaDigester.hexdigest(),160 sha1=shaDigester.hexdigest(),
161 md5=md5Digester.hexdigest())161 md5=md5Digester.hexdigest())
162 alias = LibraryFileAlias(162 LibraryFileAlias(
163 id=aliasID, content=content, filename=name.decode('UTF-8'),163 id=aliasID, content=content, filename=name.decode('UTF-8'),
164 mimetype=contentType, expires=expires,164 mimetype=contentType, expires=expires,
165 restricted=self.restricted)165 restricted=self.restricted)
@@ -356,6 +356,11 @@
356 if time.time() <= try_until:356 if time.time() <= try_until:
357 time.sleep(1)357 time.sleep(1)
358 else:358 else:
359 # There's a test (in
360 # lib/c/l/browser/tests/test_librarian.py) which
361 # simulates a librarian server error by raising this
362 # exception, so if you change the exception raised
363 # here, make sure you update the test.
359 raise LibrarianServerError(str(error))364 raise LibrarianServerError(str(error))
360 else:365 else:
361 raise366 raise