Rev 6021: Merge 2.3 into 2.4 in http://bazaar.launchpad.net/~vila/bzr/2.4-integration/
Vincent Ladeuil
v.ladeuil+lp at free.fr
Thu Aug 11 07:35:52 UTC 2011
At http://bazaar.launchpad.net/~vila/bzr/2.4-integration/
------------------------------------------------------------
revno: 6021 [merge]
revision-id: v.ladeuil+lp at free.fr-20110811073549-4grdvyrb6ytsuhf0
parent: pqm at pqm.ubuntu.com-20110718144335-8v4u0gbnwzm0vzmt
parent: pqm at pqm.ubuntu.com-20110801054736-0s5zojh4cscoxnoj
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: 2.4.0-dev
timestamp: Thu 2011-08-11 09:35:49 +0200
message:
Merge 2.3 into 2.4
modified:
bzrlib/errors.py errors.py-20050309040759-20512168c4e14fbd
bzrlib/tests/test_http.py testhttp.py-20051018020158-b2eef6e867c514d9
bzrlib/transport/http/__init__.py http_transport.py-20050711212304-506c5fd1059ace96
bzrlib/transport/http/response.py _response.py-20060613154423-a2ci7hd4iw5c7fnt-1
doc/en/release-notes/bzr-2.3.txt NEWS-20050323055033-4e00b5db738777ff
-------------- next part --------------
=== modified file 'bzrlib/errors.py'
--- a/bzrlib/errors.py 2011-06-21 11:34:52 +0000
+++ b/bzrlib/errors.py 2011-08-11 07:35:49 +0000
@@ -1737,6 +1737,19 @@
InvalidHttpResponse.__init__(self, path, msg)
+class HttpBoundaryMissing(InvalidHttpResponse):
+ """A multipart response ends with no boundary marker.
+
+ This is a special case caused by buggy proxies, described in
+ <https://bugs.launchpad.net/bzr/+bug/198646>.
+ """
+
+ _fmt = "HTTP MIME Boundary missing for %(path)s: %(msg)s"
+
+ def __init__(self, path, msg):
+ InvalidHttpResponse.__init__(self, path, msg)
+
+
class InvalidHttpContentType(InvalidHttpResponse):
_fmt = 'Invalid http Content-type "%(ctype)s" for %(path)s: %(msg)s'
=== modified file 'bzrlib/tests/test_http.py'
--- a/bzrlib/tests/test_http.py 2011-06-07 12:25:45 +0000
+++ b/bzrlib/tests/test_http.py 2011-08-11 07:35:49 +0000
@@ -1048,6 +1048,72 @@
self.assertEqual('single', t._range_hint)
+class TruncatedBeforeBoundaryRequestHandler(
+ http_server.TestingHTTPRequestHandler):
+ """Truncation before a boundary, like in bug 198646"""
+
+ _truncated_ranges = 1
+
+ def get_multiple_ranges(self, file, file_size, ranges):
+ self.send_response(206)
+ self.send_header('Accept-Ranges', 'bytes')
+ boundary = 'tagada'
+ self.send_header('Content-Type',
+ 'multipart/byteranges; boundary=%s' % boundary)
+ boundary_line = '--%s\r\n' % boundary
+ # Calculate the Content-Length
+ content_length = 0
+ for (start, end) in ranges:
+ content_length += len(boundary_line)
+ content_length += self._header_line_length(
+ 'Content-type', 'application/octet-stream')
+ content_length += self._header_line_length(
+ 'Content-Range', 'bytes %d-%d/%d' % (start, end, file_size))
+ content_length += len('\r\n') # end headers
+ content_length += end - start # + 1
+ content_length += len(boundary_line)
+ self.send_header('Content-length', content_length)
+ self.end_headers()
+
+ # Send the multipart body
+ cur = 0
+ for (start, end) in ranges:
+ if cur + self._truncated_ranges >= len(ranges):
+ # Abruptly ends the response and close the connection
+ self.close_connection = 1
+ return
+ self.wfile.write(boundary_line)
+ self.send_header('Content-type', 'application/octet-stream')
+ self.send_header('Content-Range', 'bytes %d-%d/%d'
+ % (start, end, file_size))
+ self.end_headers()
+ self.send_range_content(file, start, end - start + 1)
+ cur += 1
+ # Final boundary
+ self.wfile.write(boundary_line)
+
+
+class TestTruncatedBeforeBoundary(TestSpecificRequestHandler):
+ """Tests the case of bug 198646, disconnecting before a boundary."""
+
+ _req_handler_class = TruncatedBeforeBoundaryRequestHandler
+
+ def setUp(self):
+ super(TestTruncatedBeforeBoundary, self).setUp()
+ self.build_tree_contents([('a', '0123456789')],)
+
+ def test_readv_with_short_reads(self):
+ server = self.get_readonly_server()
+ t = self.get_readonly_transport()
+ # Force separate ranges for each offset
+ t._bytes_to_read_before_seek = 0
+ ireadv = iter(t.readv('a', ((0, 1), (2, 1), (4, 2), (9, 1))))
+ self.assertEqual((0, '0'), ireadv.next())
+ self.assertEqual((2, '2'), ireadv.next())
+ self.assertEqual((4, '45'), ireadv.next())
+ self.assertEqual((9, '9'), ireadv.next())
+
+
class LimitedRangeRequestHandler(http_server.TestingHTTPRequestHandler):
"""Errors out when range specifiers exceed the limit"""
=== modified file 'bzrlib/transport/http/__init__.py'
--- a/bzrlib/transport/http/__init__.py 2011-05-27 07:39:41 +0000
+++ b/bzrlib/transport/http/__init__.py 2011-08-11 07:35:49 +0000
@@ -271,7 +271,7 @@
cur_offset_and_size = iter_offsets.next()
except (errors.ShortReadvError, errors.InvalidRange,
- errors.InvalidHttpRange), e:
+ errors.InvalidHttpRange, errors.HttpBoundaryMissing), e:
mutter('Exception %r: %s during http._readv',e, e)
if (not isinstance(e, errors.ShortReadvError)
or retried_offset == cur_offset_and_size):
=== modified file 'bzrlib/transport/http/response.py'
--- a/bzrlib/transport/http/response.py 2009-03-23 14:59:43 +0000
+++ b/bzrlib/transport/http/response.py 2011-07-27 11:57:32 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2006, 2007 Canonical Ltd
+# Copyright (C) 2006-2011 Canonical Ltd
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -109,6 +109,13 @@
# To be on the safe side we allow it before any boundary line
boundary_line = self._file.readline()
+ if boundary_line == '':
+ # A timeout in the proxy server caused the response to end early.
+ # See launchpad bug 198646.
+ raise errors.HttpBoundaryMissing(
+ self._path,
+ self._boundary)
+
if boundary_line != '--' + self._boundary + '\r\n':
# rfc822.unquote() incorrectly unquotes strings enclosed in <>
# IIS 6 and 7 incorrectly wrap boundary strings in <>
=== modified file 'doc/en/release-notes/bzr-2.3.txt'
--- a/doc/en/release-notes/bzr-2.3.txt 2011-07-15 08:25:00 +0000
+++ b/doc/en/release-notes/bzr-2.3.txt 2011-08-11 07:35:49 +0000
@@ -32,6 +32,9 @@
.. Fixes for situations where bzr would previously crash or give incorrect
or undesirable results.
+* Cope cleanly with buggy HTTP proxies that close the socket in the middle
+ of a multipart response. (Martin Pool, #198646).
+
Documentation
*************
More information about the bazaar-commits
mailing list