~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/http/response.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2008-03-16 16:58:03 UTC
  • mfrom: (3224.3.1 news-typo)
  • Revision ID: pqm@pqm.ubuntu.com-20080316165803-tisoc9mpob9z544o
(Matt Nordhoff) Trivial NEWS typo fix

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2011 Canonical Ltd
 
1
# Copyright (C) 2006, 2007 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
"""Handlers for HTTP Responses.
18
18
 
23
23
 
24
24
 
25
25
import httplib
26
 
from cStringIO import StringIO
27
 
import rfc822
28
26
 
29
27
from bzrlib import (
30
28
    errors,
31
 
    osutils,
 
29
    trace,
32
30
    )
33
31
 
34
32
 
63
61
    # 8k chunks should be fine.
64
62
    _discarded_buf_size = 8192
65
63
 
66
 
    # maximum size of read requests -- used to avoid MemoryError issues in recv
67
 
    _max_read_size = 512 * 1024
68
 
 
69
64
    def __init__(self, path, infile):
70
65
        """Constructor.
71
66
 
90
85
 
91
86
    def set_boundary(self, boundary):
92
87
        """Define the boundary used in a multi parts message.
93
 
 
 
88
        
94
89
        The file should be at the beginning of the body, the first range
95
90
        definition is read and taken into account.
96
91
        """
107
102
            # string entity.
108
103
            # To be on the safe side we allow it before any boundary line
109
104
            boundary_line = self._file.readline()
110
 
 
111
 
        if boundary_line == '':
112
 
            # A timeout in the proxy server caused the response to end early.
113
 
            # See launchpad bug 198646.
114
 
            raise errors.HttpBoundaryMissing(
115
 
                self._path,
116
 
                self._boundary)
117
 
 
118
105
        if boundary_line != '--' + self._boundary + '\r\n':
119
 
            # rfc822.unquote() incorrectly unquotes strings enclosed in <>
120
 
            # IIS 6 and 7 incorrectly wrap boundary strings in <>
121
 
            # together they make a beautiful bug, which we will be gracious
122
 
            # about here
123
 
            if (self._unquote_boundary(boundary_line) !=
124
 
                '--' + self._boundary + '\r\n'):
125
 
                raise errors.InvalidHttpResponse(
126
 
                    self._path,
127
 
                    "Expected a boundary (%s) line, got '%s'"
128
 
                    % (self._boundary, boundary_line))
129
 
 
130
 
    def _unquote_boundary(self, b):
131
 
        return b[:2] + rfc822.unquote(b[2:-2]) + b[-2:]
 
106
            raise errors.InvalidHttpResponse(
 
107
                self._path,
 
108
                "Expected a boundary (%s) line, got '%s'" % (self._boundary,
 
109
                                                             boundary_line))
132
110
 
133
111
    def read_range_definition(self):
134
112
        """Read a new range definition in a multi parts message.
204
182
        client to clean the socket if we leave bytes unread. This may occur for
205
183
        the final boundary line of a multipart response or for any range
206
184
        request not entirely consumed by the client (due to offset coalescing)
207
 
 
208
 
        :param size:  The number of bytes to read.  Leave unspecified or pass
209
 
            -1 to read to EOF.
210
185
        """
211
186
        if (self._size > 0
212
187
            and self._pos == self._start + self._size):
226
201
                    "Can't read %s bytes across range (%s, %s)"
227
202
                    % (size, self._start, self._size))
228
203
 
229
 
        # read data from file
230
 
        buffer = StringIO()
231
 
        limited = size
232
204
        if self._size > 0:
233
205
            # Don't read past the range definition
234
206
            limited = self._start + self._size - self._pos
235
207
            if size >= 0:
236
208
                limited = min(limited, size)
237
 
        osutils.pumpfile(self._file, buffer, limited, self._max_read_size)
238
 
        data = buffer.getvalue()
239
 
 
 
209
            data = self._file.read(limited)
 
210
        else:
 
211
            # Size of file unknown, the user may have specified a size or not,
 
212
            # we delegate that to the filesocket object (-1 means read until
 
213
            # EOF)
 
214
            data = self._file.read(size)
240
215
        # Update _pos respecting the data effectively read
241
216
        self._pos += len(data)
242
217
        return data
294
269
    :param msg: An HTTPMessage containing the headers for the response
295
270
    :param data: A file-like object that can be read() to get the
296
271
                 requested data
297
 
    :return: A file-like object that can seek()+read() the
 
272
    :return: A file-like object that can seek()+read() the 
298
273
             ranges indicated by the headers.
299
274
    """
300
275
    rfile = RangeFile(url, data)