~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

  • Committer: Vincent Ladeuil
  • Date: 2008-01-03 08:49:38 UTC
  • mfrom: (3111.1.31 175524)
  • mto: This revision was merged to the branch mainline in revision 3158.
  • Revision ID: v.ladeuil+lp@free.fr-20080103084938-7kvurk5uvde2ui54
Fix bug #175524, http test servers are 1.1 compliant

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006,2007 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
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
88
85
        """
89
86
        httplib.HTTPResponse.begin(self)
90
87
        if self.status in self._body_ignored_responses:
91
 
            if self.debuglevel > 0:
 
88
            if self.debuglevel >= 2:
92
89
                print "For status: [%s]," % self.status,
93
 
                print "will ready body, length: ",
94
 
                if  self.length is not None:
95
 
                    print "[%d]" % self.length
96
 
                else:
97
 
                    print "None"
 
90
                print "will ready body, length: %s" % self.length
98
91
            if not (self.length is None or self.will_close):
99
92
                # In some cases, we just can't read the body not
100
93
                # even try or we may encounter a 104, 'Connection
102
95
                # and the server closed the connection just after
103
96
                # having issued the response headers (even if the
104
97
                # headers indicate a Content-Type...)
105
 
                body = self.fp.read(self.length)
106
 
                if self.debuglevel > 3:
 
98
                body = self.read(self.length)
 
99
                if self.debuglevel >= 9:
107
100
                    # This one can be huge and is generally not interesting
108
101
                    print "Consumed body: [%s]" % body
109
102
            self.close()
149
142
                pending += len(data)
150
143
            if pending:
151
144
                trace.mutter(
152
 
                    "bogus http server didn't give body length,"
153
 
                    "%s bytes left on the socket",
 
145
                    "%s bytes left on the HTTP socket",
154
146
                    pending)
155
147
            self.close()
156
148
        return pending
161
153
    """A custom HTTP(S) Connection, which can reset itself on a bad response"""
162
154
 
163
155
    response_class = Response
164
 
    strict = 1 # We don't support HTTP/0.9
165
156
 
166
157
    # When we detect a server responding with the whole file to range requests,
167
158
    # we want to warn. But not below a given thresold.
183
174
        return self._response
184
175
 
185
176
    def cleanup_pipe(self):
186
 
        """Make the connection believe the response has been fully processed."""
 
177
        """Read the remaining bytes of the last response if any."""
187
178
        if self._response is not None:
188
179
            pending = self._response.finish()
189
180
            # Warn the user (once)
209
200
class HTTPConnection(AbstractHTTPConnection, httplib.HTTPConnection):
210
201
 
211
202
    # XXX: Needs refactoring at the caller level.
212
 
    def __init__(self, host, port=None, strict=None, proxied_host=None):
 
203
    def __init__(self, host, port=None, proxied_host=None):
213
204
        AbstractHTTPConnection.__init__(self)
214
 
        httplib.HTTPConnection.__init__(self, host, port, strict)
 
205
        # Use strict=True since we don't support HTTP/0.9
 
206
        httplib.HTTPConnection.__init__(self, host, port, strict=True)
215
207
        self.proxied_host = proxied_host
216
208
 
217
209
    def connect(self):
220
212
        httplib.HTTPConnection.connect(self)
221
213
 
222
214
 
 
215
# FIXME: Should test for ssl availability
223
216
class HTTPSConnection(AbstractHTTPConnection, httplib.HTTPSConnection):
224
217
 
225
218
    def __init__(self, host, port=None, key_file=None, cert_file=None,
226
 
                 strict=None, proxied_host=None):
 
219
                 proxied_host=None):
227
220
        AbstractHTTPConnection.__init__(self)
 
221
        # Use strict=True since we don't support HTTP/0.9
228
222
        httplib.HTTPSConnection.__init__(self, host, port,
229
 
                                         key_file, cert_file, strict)
 
223
                                         key_file, cert_file, strict=True)
230
224
        self.proxied_host = proxied_host
231
225
 
232
226
    def connect(self):
440
434
            raise exc_type, exc_val, exc_tb
441
435
        else:
442
436
            if first_try:
443
 
                if self._debuglevel > 0:
 
437
                if self._debuglevel >= 2:
444
438
                    print 'Received exception: [%r]' % exc_val
445
439
                    print '  On connection: [%r]' % request.connection
446
440
                    method = request.get_method()
449
443
                request.connection.close()
450
444
                response = self.do_open(http_class, request, False)
451
445
            else:
452
 
                if self._debuglevel > 0:
 
446
                if self._debuglevel >= 2:
453
447
                    print 'Received second exception: [%r]' % exc_val
454
448
                    print '  On connection: [%r]' % request.connection
455
449
                if exc_type in (httplib.BadStatusLine, httplib.UnknownProtocol):
476
470
                                                       request.get_selector()),
477
471
                        orig_error=exc_val)
478
472
 
479
 
                if self._debuglevel > 0:
 
473
                if self._debuglevel >= 2:
480
474
                    print 'On connection: [%r]' % request.connection
481
475
                    method = request.get_method()
482
476
                    url = request.get_full_url()
511
505
                trace.mutter('> %s %s' % (method, url))
512
506
                hdrs = ['%s: %s' % (k, v) for k,v in headers.items()]
513
507
                trace.mutter('> ' + '\n> '.join(hdrs) + '\n')
514
 
            if self._debuglevel > 0:
515
 
                print 'Request sent: [%r]' % request
 
508
            if self._debuglevel >= 1:
 
509
                print 'Request sent: [%r] from (%s)' \
 
510
                    % (request, request.connection.sock.getsockname())
516
511
            response = connection.getresponse()
517
512
            convert_to_addinfourl = True
518
513
        except (socket.gaierror, httplib.BadStatusLine, httplib.UnknownProtocol,
532
527
#            connection.send(body)
533
528
#            response = connection.getresponse()
534
529
 
535
 
        if self._debuglevel > 0:
 
530
        if self._debuglevel >= 2:
536
531
            print 'Receives response: %r' % response
537
532
            print '  For: %r(%r)' % (request.get_method(),
538
533
                                     request.get_full_url())
547
542
            resp.code = r.status
548
543
            resp.msg = r.reason
549
544
            resp.version = r.version
550
 
            if self._debuglevel > 0:
 
545
            if self._debuglevel >= 2:
551
546
                print 'Create addinfourl: %r' % resp
552
547
                print '  For: %r(%r)' % (request.get_method(),
553
548
                                         request.get_full_url())
593
588
            # - with and without certificate
594
589
            # - with self-signed certificate
595
590
            # - with and without authentication
596
 
            # - with good and bad credentials (especially the proxy auth aound
 
591
            # - with good and bad credentials (especially the proxy auth around
597
592
            #   CONNECT)
598
593
            # - with basic and digest schemes
599
594
            # - reconnection on errors
694
689
            newurl = headers.getheaders('uri')[0]
695
690
        else:
696
691
            return
697
 
        if self._debuglevel > 0:
 
692
        if self._debuglevel >= 1:
698
693
            print 'Redirected to: %s (followed: %r)' % (newurl,
699
694
                                                        req.follow_redirections)
700
695
        if req.follow_redirections is False:
757
752
        urllib2.ProxyHandler.__init__(self, proxies)
758
753
        # First, let's get rid of urllib2 implementation
759
754
        for type, proxy in self.proxies.items():
760
 
            if self._debuglevel > 0:
 
755
            if self._debuglevel >= 3:
761
756
                print 'Will unbind %s_open for %r' % (type, proxy)
762
757
            delattr(self, '%s_open' % type)
763
758
 
766
761
        https_proxy = self.get_proxy_env_var('https')
767
762
 
768
763
        if http_proxy is not None:
769
 
            if self._debuglevel > 0:
 
764
            if self._debuglevel >= 3:
770
765
                print 'Will bind http_request for %r' % http_proxy
771
766
            setattr(self, 'http_request',
772
767
                    lambda request: self.set_proxy(request, 'http'))
773
768
 
774
769
        if https_proxy is not None:
775
 
            if self._debuglevel > 0:
 
770
            if self._debuglevel >= 3:
776
771
                print 'Will bind http_request for %r' % https_proxy
777
772
            setattr(self, 'https_request',
778
773
                    lambda request: self.set_proxy(request, 'https'))
823
818
            return request
824
819
 
825
820
        proxy = self.get_proxy_env_var(type)
826
 
        if self._debuglevel > 0:
 
821
        if self._debuglevel >= 3:
827
822
            print 'set_proxy %s_request for %r' % (type, proxy)
828
823
        # FIXME: python 2.5 urlparse provides a better _parse_proxy which can
829
824
        # grok user:password@host:port as well as
847
842
        else:
848
843
            phost = host + ':%d' % port
849
844
        request.set_proxy(phost, type)
850
 
        if self._debuglevel > 0:
 
845
        if self._debuglevel >= 3:
851
846
            print 'set_proxy: proxy set to %s://%s' % (type, phost)
852
847
        return request
853
848
 
948
943
                # We already tried that, give up
949
944
                return None
950
945
 
 
946
            # Housekeeping
 
947
            request.connection.cleanup_pipe()
951
948
            response = self.parent.open(request)
952
949
            if response:
953
950
                self.auth_successful(request, response)
1350
1347
            )
1351
1348
 
1352
1349
        self.open = self._opener.open
1353
 
        if DEBUG >= 3:
 
1350
        if DEBUG >= 9:
1354
1351
            # When dealing with handler order, it's easy to mess
1355
1352
            # things up, the following will help understand which
1356
1353
            # handler is used, when and for what.