13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
178
179
content_length += self._header_line_length(
179
180
'Content-Range', 'bytes %d-%d/%d' % (start, end, file_size))
180
181
content_length += len('\r\n') # end headers
181
content_length += end - start + 1
182
content_length += end - start # + 1
182
183
content_length += len(boundary_line)
183
184
self.send_header('Content-length', content_length)
184
185
self.end_headers()
283
284
return self._translate_path(path)
285
286
def _translate_path(self, path):
286
"""Translate a /-separated PATH to the local filename syntax.
288
Note that we're translating http URLs here, not file URLs.
289
The URL root location is the server's startup directory.
290
Components that mean special things to the local file system
291
(e.g. drive or directory names) are ignored. (XXX They should
292
probably be diagnosed.)
294
Override from python standard library to stop it calling os.getcwd()
296
# abandon query parameters
297
path = urlparse.urlparse(path)[2]
298
path = posixpath.normpath(urllib.unquote(path))
299
path = path.decode('utf-8')
300
words = path.split('/')
301
words = filter(None, words)
303
for num, word in enumerate(words):
287
return SimpleHTTPServer.SimpleHTTPRequestHandler.translate_path(
290
if sys.platform == 'win32':
291
# On win32 you cannot access non-ascii filenames without
292
# decoding them into unicode first.
293
# However, under Linux, you can access bytestream paths
294
# without any problems. If this function was always active
295
# it would probably break tests when LANG=C was set
296
def _translate_path(self, path):
297
"""Translate a /-separated PATH to the local filename syntax.
299
For bzr, all url paths are considered to be utf8 paths.
300
On Linux, you can access these paths directly over the bytestream
301
request, but on win32, you must decode them, and access them
304
# abandon query parameters
305
path = urlparse.urlparse(path)[2]
306
path = posixpath.normpath(urllib.unquote(path))
307
path = path.decode('utf-8')
308
words = path.split('/')
309
words = filter(None, words)
305
312
drive, word = os.path.splitdrive(word)
306
head, word = os.path.split(word)
307
if word in (os.curdir, os.pardir): continue
308
path = os.path.join(path, word)
313
head, word = os.path.split(word)
314
if word in (os.curdir, os.pardir): continue
315
path = os.path.join(path, word)
312
319
class TestingHTTPServerMixin:
317
324
# server), allowing dynamic behaviors to be defined from
318
325
# the tests cases.
319
326
self.test_case_server = test_case_server
320
self._home_dir = test_case_server._home_dir
322
def stop_server(self):
323
329
"""Called to clean-up the server.
325
331
Since the server may be (surely is, even) in a blocking listen, we
326
332
shutdown its socket before closing it.
344
350
# WSAENOTCONN (10057) 'Socket is not connected' is harmless on
345
351
# windows (occurs before the first connection attempt
346
352
# vila--20071230)
348
# 'Socket is not connected' can also occur on OSX, with a
349
# "regular" ENOTCONN (when something went wrong during test case
350
# setup leading to self.setUp() *not* being called but
351
# self.stop_server() still being called -- vila20081106
352
if not len(e.args) or e.args[0] not in (errno.ENOTCONN, 10057):
353
if not len(e.args) or e.args[0] != 10057:
354
355
# Let the server properly close the socket
355
356
self.server_close()
358
358
class TestingHTTPServer(SocketServer.TCPServer, TestingHTTPServerMixin):
360
360
def __init__(self, server_address, request_handler_class,
384
384
self.daemon_threads = True
386
def process_request_thread(self, request, client_address):
387
SocketServer.ThreadingTCPServer.process_request_thread(
388
self, request, client_address)
389
# Under some circumstances (as in bug #383920), we need to force the
390
# shutdown as python delays it until gc occur otherwise and the client
393
# The request process has been completed, the thread is about to
394
# die, let's shutdown the socket if we can.
395
request.shutdown(socket.SHUT_RDWR)
396
except (socket.error, select.error), e:
397
if e[0] in (errno.EBADF, errno.ENOTCONN):
398
# Right, the socket is already down
404
387
class HttpServer(transport.Server):
405
388
"""A test server for http transports.
438
421
# Allows tests to verify number of GET requests issued
439
422
self.GET_request_nb = 0
441
def create_httpd(self, serv_cls, rhandler_cls):
442
return serv_cls((self.host, self.port), self.request_handler, self)
445
return "%s(%s:%s)" % \
446
(self.__class__.__name__, self.host, self.port)
448
424
def _get_httpd(self):
449
425
if self._httpd is None:
450
426
rhandler = self.request_handler
462
438
if serv_cls is None:
463
439
raise httplib.UnknownProtocol(proto_vers)
465
self._httpd = self.create_httpd(serv_cls, rhandler)
466
self.host, self.port = self._httpd.socket.getsockname()
441
self._httpd = serv_cls((self.host, self.port), rhandler, self)
442
host, self.port = self._httpd.socket.getsockname()
467
443
return self._httpd
469
445
def _http_start(self):
494
470
httpd.handle_request()
495
471
except socket.timeout:
497
except (socket.error, select.error), e:
498
if (e[0] == errno.EBADF
499
or (sys.platform == 'win32' and e[0] == 10038)):
500
# Starting with python-2.6, handle_request may raise socket
501
# or select exceptions when the server is shut down (as we
503
# 10038 = WSAENOTSOCK
504
# http://msdn.microsoft.com/en-us/library/ms740668%28VS.85%29.aspx
509
474
def _get_remote_url(self, path):
510
475
path_parts = path.split(os.path.sep)
522
487
"""Capture Server log output."""
523
488
self.logs.append(format % args)
525
def start_server(self, backing_transport_server=None):
526
"""See bzrlib.transport.Server.start_server.
490
def setUp(self, backing_transport_server=None):
491
"""See bzrlib.transport.Server.setUp.
528
493
:param backing_transport_server: The transport that requests over this
529
494
protocol should be forwarded to. Note that this is currently not
530
495
supported for HTTP.
532
497
# XXX: TODO: make the server back onto vfs_server rather than local
534
if not (backing_transport_server is None
535
or isinstance(backing_transport_server,
536
test_server.LocalURLServer)):
537
raise AssertionError(
538
"HTTPServer currently assumes local transport, got %s" % \
539
backing_transport_server)
499
assert backing_transport_server is None or \
500
isinstance(backing_transport_server, local.LocalURLServer), \
501
"HTTPServer currently assumes local transport, got %s" % \
502
backing_transport_server
540
503
self._home_dir = os.getcwdu()
541
504
self._local_path_parts = self._home_dir.split(os.path.sep)
542
505
self._http_base_url = None