1
# Copyright (C) 2006-2010 Canonical Ltd
1
# Copyright (C) 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
89
88
errno.ECONNABORTED, errno.EBADF)):
92
error_content_type = 'text/plain'
93
error_message_format = '''\
98
def send_error(self, code, message=None):
99
"""Send and log an error reply.
101
We redefine the python-provided version to be able to set a
102
``Content-Length`` header as some http/1.1 clients complain otherwise
105
:param code: The HTTP error code.
107
:param message: The explanation of the error code, Defaults to a short
113
message = self.responses[code][0]
116
self.log_error("code %d, message %s", code, message)
117
content = (self.error_message_format %
118
{'code': code, 'message': message})
119
self.send_response(code, message)
120
self.send_header("Content-Type", self.error_content_type)
121
self.send_header("Content-Length", "%d" % len(content))
122
self.send_header('Connection', 'close')
124
if self.command != 'HEAD' and code >= 200 and code not in (204, 304):
125
self.wfile.write(content)
127
91
_range_regexp = re.compile(r'^(?P<start>\d+)-(?P<end>\d+)$')
128
92
_tail_regexp = re.compile(r'^-(?P<tail>\d+)$')
354
318
self.test_case_server = test_case_server
355
319
self._home_dir = test_case_server._home_dir
357
def stop_server(self):
358
322
"""Called to clean-up the server.
360
324
Since the server may be (surely is, even) in a blocking listen, we
383
347
# 'Socket is not connected' can also occur on OSX, with a
384
348
# "regular" ENOTCONN (when something went wrong during test case
385
349
# setup leading to self.setUp() *not* being called but
386
# self.stop_server() still being called -- vila20081106
350
# self.tearDown() still being called -- vila20081106
387
351
if not len(e.args) or e.args[0] not in (errno.ENOTCONN, 10057):
389
353
# Let the server properly close the socket
498
462
raise httplib.UnknownProtocol(proto_vers)
500
464
self._httpd = self.create_httpd(serv_cls, rhandler)
501
self.host, self.port = self._httpd.socket.getsockname()
465
host, self.port = self._httpd.socket.getsockname()
502
466
return self._httpd
504
468
def _http_start(self):
530
494
except socket.timeout:
532
496
except (socket.error, select.error), e:
533
if (e[0] == errno.EBADF
534
or (sys.platform == 'win32' and e[0] == 10038)):
535
# Starting with python-2.6, handle_request may raise socket
536
# or select exceptions when the server is shut down (as we
538
# 10038 = WSAENOTSOCK
539
# http://msdn.microsoft.com/en-us/library/ms740668%28VS.85%29.aspx
497
if e[0] == errno.EBADF:
498
# Starting with python-2.6, handle_request may raise socket
499
# or select exceptions when the server is shut down (as we
544
505
def _get_remote_url(self, path):
545
506
path_parts = path.split(os.path.sep)
557
518
"""Capture Server log output."""
558
519
self.logs.append(format % args)
560
def start_server(self, backing_transport_server=None):
561
"""See bzrlib.transport.Server.start_server.
521
def setUp(self, backing_transport_server=None):
522
"""See bzrlib.transport.Server.setUp.
563
524
:param backing_transport_server: The transport that requests over this
564
525
protocol should be forwarded to. Note that this is currently not
567
528
# XXX: TODO: make the server back onto vfs_server rather than local
569
if not (backing_transport_server is None
570
or isinstance(backing_transport_server,
571
test_server.LocalURLServer)):
530
if not (backing_transport_server is None or \
531
isinstance(backing_transport_server, local.LocalURLServer)):
572
532
raise AssertionError(
573
533
"HTTPServer currently assumes local transport, got %s" % \
574
534
backing_transport_server)
594
554
self._http_starting.release()
597
def stop_server(self):
598
self._httpd.stop_server()
558
"""See bzrlib.transport.Server.tearDown."""
559
self._httpd.tearDown()
599
560
self._http_running = False
600
561
# We don't need to 'self._http_thread.join()' here since the thread is
601
562
# a daemonic one and will be garbage collected anyway. Joining just