1
# Copyright (C) 2005, 2006 Canonical Ltd
1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
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
21
21
from bzrlib import (
25
from bzrlib.trace import mutter
26
from bzrlib.transport.http import HttpTransportBase
27
# TODO: handle_response should be integrated into the _urllib2_wrappers
26
from bzrlib.transport import http
27
# TODO: handle_response should be integrated into the http/__init__.py
28
28
from bzrlib.transport.http.response import handle_response
29
29
from bzrlib.transport.http._urllib2_wrappers import (
35
class HttpTransport_urllib(HttpTransportBase):
35
class HttpTransport_urllib(http.HttpTransportBase):
36
36
"""Python urllib transport for http and https."""
38
38
# In order to debug we have to issue our traces in sync with
50
50
self._opener = self._opener_class()
52
def _remote_path(self, relpath):
53
"""Produce absolute path, adjusting protocol."""
54
relative = urlutils.unescape(relpath).encode('utf-8')
55
path = self._combine_paths(self._path, relative)
56
# urllib2 will be confused if it find authentication
57
# info (user, password) in the urls. So we handle them separatly.
59
# rhaaaa ! confused where ? confused when ? --vila 20070922
60
return self._unsplit_url(self._unqualified_scheme,
61
None, None, self._host, self._port, path)
63
52
def _perform(self, request):
64
53
"""Send the request to the server and handles common errors.
70
59
# Give back shared info
71
60
request.connection = connection
72
61
(auth, proxy_auth) = self._get_credentials()
62
# Clean the httplib.HTTPConnection pipeline in case the previous
63
# request couldn't do it
64
connection.cleanup_pipe()
74
# First request, intialize credentials.
66
# First request, initialize credentials.
75
67
# scheme and realm will be set by the _urllib2_wrappers.AuthHandler
77
password = self._password
78
auth = dict(host=self._host, port=self._port,
79
user=user, password=password,
80
protocol=self._unqualified_scheme,
82
# Proxy initialization will be done by first proxied request
68
auth = self._create_auth()
69
# Proxy initialization will be done by the first proxied request
83
70
proxy_auth = dict()
84
71
# Ensure authentication info is provided
85
72
request.auth = auth
86
73
request.proxy_auth = proxy_auth
88
mutter('%s: [%s]' % (request.method, request.get_full_url()))
89
75
if self._debuglevel > 0:
90
76
print 'perform: %s base: %s, url: %s' % (request.method, self.base,
91
77
request.get_full_url())
124
110
if range_header is not None:
125
111
accepted_errors.append(206)
126
112
accepted_errors.append(400)
113
accepted_errors.append(416)
127
114
bytes = 'bytes=' + range_header
128
115
headers = {'Range': bytes}
134
121
code = response.code
135
122
if code == 404: # not found
136
self._get_connection().fake_close()
137
123
raise errors.NoSuchFile(abspath)
124
elif code in (400, 416):
125
# We don't know which, but one of the ranges we specified was
127
raise errors.InvalidHttpRange(abspath, range_header,
128
'Server return code %d' % code)
139
data = handle_response(abspath, code, response.headers, response)
140
# Close response to free the httplib.HTTPConnection pipeline
141
self._get_connection().fake_close()
130
data = handle_response(abspath, code, response.info(), response)
142
131
return code, data
144
133
def _post(self, body_bytes):
145
134
abspath = self._remote_path('.bzr/smart')
146
135
response = self._perform(Request('POST', abspath, body_bytes))
147
136
code = response.code
148
data = handle_response(abspath, code, response.headers, response)
149
# Close response to free the httplib.HTTPConnection pipeline
150
self._get_connection().fake_close()
137
data = handle_response(abspath, code, response.info(), response)
151
138
return code, data
153
140
def _head(self, relpath):
178
164
def get_test_permutations():
179
165
"""Return the permutations to be used in testing."""
180
from bzrlib.tests.HttpServer import HttpServer_urllib
166
from bzrlib.tests.http_server import HttpServer_urllib
181
167
return [(HttpTransport_urllib, HttpServer_urllib),