/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

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

merge bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
32
32
handle authentication schemes.
33
33
"""
34
34
 
35
 
# TODO: now that we have -Dhttp most of the needs should be covered in a more
36
 
# accessible way (i.e. no need to edit the source), if experience confirms
37
 
# that, delete all DEBUG uses -- vila20071130 (happy birthday).
38
35
DEBUG = 0
39
36
 
40
37
# FIXME: Oversimplifying, two kind of exceptions should be
77
74
    # Some responses have bodies in which we have no interest
78
75
    _body_ignored_responses = [301,302, 303, 307, 401, 403, 404]
79
76
 
80
 
    def __init__(self, *args, **kwargs):
81
 
        httplib.HTTPResponse.__init__(self, *args, **kwargs)
82
 
 
83
77
    def begin(self):
84
78
        """Begin to read the response from the server.
85
79
 
90
84
        """
91
85
        httplib.HTTPResponse.begin(self)
92
86
        if self.status in self._body_ignored_responses:
93
 
            if self.debuglevel > 0:
 
87
            if self.debuglevel >= 2:
94
88
                print "For status: [%s]," % self.status,
95
 
                print "will ready body, length: ",
96
 
                if  self.length is not None:
97
 
                    print "[%d]" % self.length
98
 
                else:
99
 
                    print "None"
 
89
                print "will ready body, length: %s" % self.length
100
90
            if not (self.length is None or self.will_close):
101
91
                # In some cases, we just can't read the body not
102
92
                # even try or we may encounter a 104, 'Connection
104
94
                # and the server closed the connection just after
105
95
                # having issued the response headers (even if the
106
96
                # headers indicate a Content-Type...)
107
 
                body = self.fp.read(self.length)
108
 
                if self.debuglevel > 3:
 
97
                body = self.read(self.length)
 
98
                if self.debuglevel >= 9:
109
99
                    # This one can be huge and is generally not interesting
110
100
                    print "Consumed body: [%s]" % body
111
101
            self.close()
122
112
            # below we keep the socket with the server opened.
123
113
            self.will_close = False
124
114
 
 
115
    # in finish() below, we may have to discard several MB in the worst
 
116
    # case. To avoid buffering that much, we read and discard by chunks
 
117
    # instead. The underlying file is either a socket or a StringIO, so reading
 
118
    # 8k chunks should be fine.
 
119
    _discarded_buf_size = 8192
 
120
 
125
121
    def finish(self):
126
122
        """Finish reading the body.
127
123
 
130
126
        persistent connection. If we don't use a persistent connection, well,
131
127
        nothing will block the next request since a new connection will be
132
128
        issued anyway.
 
129
 
 
130
        :return: the number of bytes left on the socket (may be None)
133
131
        """
 
132
        pending = None
134
133
        if not self.isclosed():
135
134
            # Make sure nothing was left to be read on the socket
136
 
            data = self.read(self.length)
 
135
            pending = 0
 
136
            while self.length and self.length > self._discarded_buf_size:
 
137
                data = self.read(self._discarded_buf_size)
 
138
                pending += len(data)
 
139
            if self.length:
 
140
                data = self.read(self.length)
 
141
                pending += len(data)
 
142
            if pending:
 
143
                trace.mutter(
 
144
                    "%s bytes left on the HTTP socket",
 
145
                    pending)
137
146
            self.close()
 
147
        return pending
138
148
 
139
149
 
140
150
# Not inheriting from 'object' because httplib.HTTPConnection doesn't.
143
153
 
144
154
    response_class = Response
145
155
 
 
156
    # When we detect a server responding with the whole file to range requests,
 
157
    # we want to warn. But not below a given thresold.
 
158
    _range_warning_thresold = 1024 * 1024
 
159
 
146
160
    def __init__(self):
147
161
        self._response = None
 
162
        self._ranges_received_whole_file = None
148
163
 
149
164
    def _mutter_connect(self):
150
 
        netloc = self.host
151
 
        if self.port is not None:
152
 
            netloc += ':%d' % self.port
 
165
        netloc = '%s:%s' % (self.host, self.port)
153
166
        if self.proxied_host is not None:
154
167
            netloc += '(proxy for %s)' % self.proxied_host
155
168
        trace.mutter('* About to connect() to %s' % netloc)
160
173
        return self._response
161
174
 
162
175
    def cleanup_pipe(self):
163
 
        """Make the connection believes the response have been fully handled.
164
 
 
165
 
        That makes the httplib.HTTPConnection happy
166
 
        """
 
176
        """Read the remaining bytes of the last response if any."""
167
177
        if self._response is not None:
168
 
            self._response.finish()
 
178
            pending = self._response.finish()
 
179
            # Warn the user (once)
 
180
            if (self._ranges_received_whole_file is None
 
181
                and self._response.status == 200
 
182
                and pending and pending > self._range_warning_thresold
 
183
                ):
 
184
                self._ranges_received_whole_file = True
 
185
                trace.warning(
 
186
                    'Got a 200 response when asking for multiple ranges,'
 
187
                    ' does your server at %s:%s support range requests?',
 
188
                    self.host, self.port)
169
189
            self._response = None
170
190
        # Preserve our preciousss
171
191
        sock = self.sock
421
441
            raise exc_type, exc_val, exc_tb
422
442
        else:
423
443
            if first_try:
424
 
                if self._debuglevel > 0:
 
444
                if self._debuglevel >= 2:
425
445
                    print 'Received exception: [%r]' % exc_val
426
446
                    print '  On connection: [%r]' % request.connection
427
447
                    method = request.get_method()
430
450
                request.connection.close()
431
451
                response = self.do_open(http_class, request, False)
432
452
            else:
433
 
                if self._debuglevel > 0:
 
453
                if self._debuglevel >= 2:
434
454
                    print 'Received second exception: [%r]' % exc_val
435
455
                    print '  On connection: [%r]' % request.connection
436
456
                if exc_type in (httplib.BadStatusLine, httplib.UnknownProtocol):
457
477
                                                       request.get_selector()),
458
478
                        orig_error=exc_val)
459
479
 
460
 
                if self._debuglevel > 0:
 
480
                if self._debuglevel >= 2:
461
481
                    print 'On connection: [%r]' % request.connection
462
482
                    method = request.get_method()
463
483
                    url = request.get_full_url()
492
512
                trace.mutter('> %s %s' % (method, url))
493
513
                hdrs = ['%s: %s' % (k, v) for k,v in headers.items()]
494
514
                trace.mutter('> ' + '\n> '.join(hdrs) + '\n')
495
 
            if self._debuglevel > 0:
496
 
                print 'Request sent: [%r]' % request
 
515
            if self._debuglevel >= 1:
 
516
                print 'Request sent: [%r] from (%s)' \
 
517
                    % (request, request.connection.sock.getsockname())
497
518
            response = connection.getresponse()
498
519
            convert_to_addinfourl = True
499
520
        except (socket.gaierror, httplib.BadStatusLine, httplib.UnknownProtocol,
513
534
#            connection.send(body)
514
535
#            response = connection.getresponse()
515
536
 
516
 
        if self._debuglevel > 0:
 
537
        if self._debuglevel >= 2:
517
538
            print 'Receives response: %r' % response
518
539
            print '  For: %r(%r)' % (request.get_method(),
519
540
                                     request.get_full_url())
528
549
            resp.code = r.status
529
550
            resp.msg = r.reason
530
551
            resp.version = r.version
531
 
            if self._debuglevel > 0:
 
552
            if self._debuglevel >= 2:
532
553
                print 'Create addinfourl: %r' % resp
533
554
                print '  For: %r(%r)' % (request.get_method(),
534
555
                                         request.get_full_url())
675
696
            newurl = headers.getheaders('uri')[0]
676
697
        else:
677
698
            return
678
 
        if self._debuglevel > 0:
 
699
        if self._debuglevel >= 1:
679
700
            print 'Redirected to: %s (followed: %r)' % (newurl,
680
701
                                                        req.follow_redirections)
681
702
        if req.follow_redirections is False:
738
759
        urllib2.ProxyHandler.__init__(self, proxies)
739
760
        # First, let's get rid of urllib2 implementation
740
761
        for type, proxy in self.proxies.items():
741
 
            if self._debuglevel > 0:
 
762
            if self._debuglevel >= 3:
742
763
                print 'Will unbind %s_open for %r' % (type, proxy)
743
764
            delattr(self, '%s_open' % type)
744
765
 
747
768
        https_proxy = self.get_proxy_env_var('https')
748
769
 
749
770
        if http_proxy is not None:
750
 
            if self._debuglevel > 0:
 
771
            if self._debuglevel >= 3:
751
772
                print 'Will bind http_request for %r' % http_proxy
752
773
            setattr(self, 'http_request',
753
774
                    lambda request: self.set_proxy(request, 'http'))
754
775
 
755
776
        if https_proxy is not None:
756
 
            if self._debuglevel > 0:
 
777
            if self._debuglevel >= 3:
757
778
                print 'Will bind http_request for %r' % https_proxy
758
779
            setattr(self, 'https_request',
759
780
                    lambda request: self.set_proxy(request, 'https'))
804
825
            return request
805
826
 
806
827
        proxy = self.get_proxy_env_var(type)
807
 
        if self._debuglevel > 0:
 
828
        if self._debuglevel >= 3:
808
829
            print 'set_proxy %s_request for %r' % (type, proxy)
809
830
        # FIXME: python 2.5 urlparse provides a better _parse_proxy which can
810
831
        # grok user:password@host:port as well as
828
849
        else:
829
850
            phost = host + ':%d' % port
830
851
        request.set_proxy(phost, type)
831
 
        if self._debuglevel > 0:
 
852
        if self._debuglevel >= 3:
832
853
            print 'set_proxy: proxy set to %s://%s' % (type, phost)
833
854
        return request
834
855
 
929
950
                # We already tried that, give up
930
951
                return None
931
952
 
 
953
            # Housekeeping
 
954
            request.connection.cleanup_pipe()
932
955
            response = self.parent.open(request)
933
956
            if response:
934
957
                self.auth_successful(request, response)
1017
1040
        the prompt, so we build the prompt from the authentication dict which
1018
1041
        contains all the needed parts.
1019
1042
 
1020
 
        Also, hhtp and proxy AuthHandlers present different prompts to the
1021
 
        user. The daughter classes hosuld implements a public
 
1043
        Also, http and proxy AuthHandlers present different prompts to the
 
1044
        user. The daughter classes should implements a public
1022
1045
        build_password_prompt using this method.
1023
1046
        """
1024
1047
        prompt = '%s' % auth['protocol'].upper() + ' %(user)s@%(host)s'
1331
1354
            )
1332
1355
 
1333
1356
        self.open = self._opener.open
1334
 
        if DEBUG >= 3:
 
1357
        if DEBUG >= 9:
1335
1358
            # When dealing with handler order, it's easy to mess
1336
1359
            # things up, the following will help understand which
1337
1360
            # handler is used, when and for what.