~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

(vila) Default to no ssl cert verification on osx and windows (Vincent
 Ladeuil)

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
 
24
24
from __future__ import absolute_import
25
25
 
26
 
import os
27
26
import httplib
28
27
from cStringIO import StringIO
29
28
import rfc822
34
33
    )
35
34
 
36
35
 
37
 
class ResponseFile(object):
38
 
    """A wrapper around the http socket containing the result of a GET request.
39
 
 
40
 
    Only read() and seek() (forward) are supported.
41
 
    """
42
 
    def __init__(self, path, infile):
43
 
        """Constructor.
44
 
 
45
 
        :param path: File url, for error reports.
46
 
 
47
 
        :param infile: File-like socket set at body start.
48
 
        """
49
 
        self._path = path
50
 
        self._file = infile
51
 
        self._pos = 0
52
 
 
53
 
    def close(self):
54
 
        """Close this file.
55
 
 
56
 
        Dummy implementation for consistency with the 'file' API.
57
 
        """
58
 
 
59
 
    def read(self, size=-1):
60
 
        """Read size bytes from the current position in the file.
61
 
 
62
 
        :param size:  The number of bytes to read.  Leave unspecified or pass
63
 
            -1 to read to EOF.
64
 
        """
65
 
        data =  self._file.read(size)
66
 
        self._pos += len(data)
67
 
        return data
68
 
 
69
 
    def seek(self, offset, whence=os.SEEK_SET):
70
 
        if whence == os.SEEK_SET:
71
 
            if offset < self._pos:
72
 
                raise AsserttionError(
73
 
                    "Can't seek backwards, pos: %s, offset: %s"
74
 
                    % (self._pos, offfset))
75
 
            to_discard = offset - self._pos
76
 
        elif whence == os.SEEK_CUR:
77
 
            to_discard = offset
78
 
        else:
79
 
            raise AssertionError("Can't seek backwards")
80
 
        if to_discard:
81
 
            # Just discard the unwanted bytes
82
 
            self.read(to_discard)
83
 
 
84
36
# A RangeFile expects the following grammar (simplified to outline the
85
37
# assumptions we rely upon).
86
38
 
87
 
# file: single_range
 
39
# file: whole_file
 
40
#     | single_range
88
41
#     | multiple_range
89
42
 
 
43
# whole_file: [content_length_header] data
 
44
 
90
45
# single_range: content_range_header data
91
46
 
92
47
# multiple_range: boundary_header boundary (content_range_header data boundary)+
93
48
 
94
 
class RangeFile(ResponseFile):
 
49
class RangeFile(object):
95
50
    """File-like object that allow access to partial available data.
96
51
 
97
52
    All accesses should happen sequentially since the acquisition occurs during
116
71
        """Constructor.
117
72
 
118
73
        :param path: File url, for error reports.
119
 
 
120
74
        :param infile: File-like socket set at body start.
121
75
        """
122
 
        super(RangeFile, self).__init__(path, infile)
 
76
        self._path = path
 
77
        self._file = infile
123
78
        self._boundary = None
124
79
        # When using multi parts response, this will be set with the headers
125
80
        # associated with the range currently read.
343
298
    :return: A file-like object that can seek()+read() the
344
299
             ranges indicated by the headers.
345
300
    """
 
301
    rfile = RangeFile(url, data)
346
302
    if code == 200:
347
303
        # A whole file
348
 
        rfile = ResponseFile(url, data)
 
304
        size = msg.getheader('content-length', None)
 
305
        if size is None:
 
306
            size = -1
 
307
        else:
 
308
            size = int(size)
 
309
        rfile.set_range(0, size)
349
310
    elif code == 206:
350
 
        rfile = RangeFile(url, data)
351
311
        content_type = msg.getheader('content-type', None)
352
312
        if content_type is None:
353
313
            # When there is no content-type header we treat the response as