/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

  • Committer: John Arbash Meinel
  • Date: 2008-06-05 16:27:16 UTC
  • mfrom: (3475 +trunk)
  • mto: This revision was merged to the branch mainline in revision 3476.
  • Revision ID: john@arbash-meinel.com-20080605162716-a3hn238tnctbfd8j
merge bzr.dev, resolve NEWS

Show diffs side-by-side

added added

removed removed

Lines of Context:
30
30
 
31
31
And a custom Request class that lets us track redirections, and
32
32
handle authentication schemes.
 
33
 
 
34
For coherency with python libraries, we use capitalized header names throughout
 
35
the code, even if the header names will be titled just before sending the
 
36
request (see AbstractHTTPHandler.do_open).
33
37
"""
34
38
 
35
39
DEBUG = 0
64
68
    )
65
69
 
66
70
 
 
71
class _BufferedMakefileSocket(object):
 
72
 
 
73
    def __init__(self, sock):
 
74
        self.sock = sock
 
75
 
 
76
    def makefile(self, mode='r', bufsize=-1):
 
77
        return self.sock.makefile(mode, 65536)
 
78
 
 
79
    def __getattr__(self, name):
 
80
        return getattr(self.sock, name)
 
81
 
 
82
 
67
83
# We define our own Response class to keep our httplib pipe clean
68
84
class Response(httplib.HTTPResponse):
69
85
    """Custom HTTPResponse, to avoid the need to decorate.
81
97
    # 8k chunks should be fine.
82
98
    _discarded_buf_size = 8192
83
99
 
 
100
    def __init__(self, sock, *args, **kwargs):
 
101
        # httplib creates a fileobject that doesn't do buffering, which
 
102
        # makes fp.readline() very expensive because it only reads one byte
 
103
        # at a time.  So we wrap the socket in an object that forces
 
104
        # sock.makefile to make a buffered file.
 
105
        sock = _BufferedMakefileSocket(sock)
 
106
        httplib.HTTPResponse.__init__(self, sock, *args, **kwargs)
 
107
 
84
108
    def begin(self):
85
109
        """Begin to read the response from the server.
86
110
 
289
313
        # confused
290
314
        Request.__init__(self, 'CONNECT', request.get_full_url(),
291
315
                         connection=request.connection)
292
 
        assert request.proxied_host is not None
 
316
        if request.proxied_host is None:
 
317
            raise AssertionError()
293
318
        self.proxied_host = request.proxied_host
294
319
 
295
320
    def get_selector(self):
386
411
    _default_headers = {'Pragma': 'no-cache',
387
412
                        'Cache-control': 'max-age=0',
388
413
                        'Connection': 'Keep-Alive',
389
 
                        # FIXME: Spell it User-*A*gent once we
390
 
                        # know how to properly avoid bogus
391
 
                        # urllib2 using capitalize() for headers
392
 
                        # instead of title(sp?).
393
414
                        'User-agent': 'bzr/%s (urllib)' % bzrlib_version,
394
415
                        'Accept': '*/*',
395
416
                        }
482
503
        The request will be retried once if it fails.
483
504
        """
484
505
        connection = request.connection
485
 
        assert connection is not None, \
486
 
            'Cannot process a request without a connection'
 
506
        if connection is None:
 
507
            raise AssertionError(
 
508
                'Cannot process a request without a connection')
487
509
 
488
510
        # Get all the headers
489
511
        headers = {}
490
512
        headers.update(request.header_items())
491
513
        headers.update(request.unredirected_hdrs)
 
514
        # Some servers or proxies will choke on headers not properly
 
515
        # cased. httplib/urllib/urllib2 all use capitalize to get canonical
 
516
        # header names, but only python2.5 urllib2 use title() to fix them just
 
517
        # before sending the request. And not all versions of python 2.5 do
 
518
        # that. Since we replace urllib2.AbstractHTTPHandler.do_open we do it
 
519
        # ourself below.
 
520
        headers = dict((name.title(), val) for name, val in headers.iteritems())
492
521
 
493
522
        try:
494
523
            method = request.get_method()
534
563
            req = request
535
564
            r = response
536
565
            r.recv = r.read
537
 
            fp = socket._fileobject(r)
 
566
            fp = socket._fileobject(r, bufsize=65536)
538
567
            resp = urllib2.addinfourl(fp, r.msg, req.get_full_url())
539
568
            resp.code = r.status
540
569
            resp.msg = r.reason
575
604
 
576
605
    def https_open(self, request):
577
606
        connection = request.connection
578
 
        assert isinstance(connection, HTTPSConnection)
579
607
        if connection.sock is None and \
580
608
                connection.proxied_host is not None and \
581
609
                request.get_method() != 'CONNECT' : # Don't loop
1313
1341
 
1314
1342
    def http_error_default(self, req, fp, code, msg, hdrs):
1315
1343
        if code == 403:
1316
 
            raise errors.TransportError('Server refuses to fullfil the request')
 
1344
            raise errors.TransportError(
 
1345
                'Server refuses to fulfill the request (403 Forbidden)'
 
1346
                ' for %s' % req.get_full_url())
1317
1347
        else:
1318
1348
            raise errors.InvalidHttpResponse(req.get_full_url(),
1319
1349
                                             'Unable to handle http code %d: %s'