1
# Copyright (C) 2006, 2007 Canonical Ltd
1
# Copyright (C) 2006-2010 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
88
89
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)
91
127
_range_regexp = re.compile(r'^(?P<start>\d+)-(?P<end>\d+)$')
92
128
_tail_regexp = re.compile(r'^-(?P<tail>\d+)$')
318
354
self.test_case_server = test_case_server
319
355
self._home_dir = test_case_server._home_dir
357
def stop_server(self):
322
358
"""Called to clean-up the server.
324
360
Since the server may be (surely is, even) in a blocking listen, we
347
383
# 'Socket is not connected' can also occur on OSX, with a
348
384
# "regular" ENOTCONN (when something went wrong during test case
349
385
# setup leading to self.setUp() *not* being called but
350
# self.tearDown() still being called -- vila20081106
386
# self.stop_server() still being called -- vila20081106
351
387
if not len(e.args) or e.args[0] not in (errno.ENOTCONN, 10057):
353
389
# Let the server properly close the socket
462
498
raise httplib.UnknownProtocol(proto_vers)
464
500
self._httpd = self.create_httpd(serv_cls, rhandler)
465
host, self.port = self._httpd.socket.getsockname()
501
self.host, self.port = self._httpd.socket.getsockname()
466
502
return self._httpd
468
504
def _http_start(self):
494
530
except socket.timeout:
496
532
except (socket.error, select.error), e:
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
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
505
544
def _get_remote_url(self, path):
506
545
path_parts = path.split(os.path.sep)
518
557
"""Capture Server log output."""
519
558
self.logs.append(format % args)
521
def setUp(self, backing_transport_server=None):
522
"""See bzrlib.transport.Server.setUp.
560
def start_server(self, backing_transport_server=None):
561
"""See bzrlib.transport.Server.start_server.
524
563
:param backing_transport_server: The transport that requests over this
525
564
protocol should be forwarded to. Note that this is currently not
528
567
# XXX: TODO: make the server back onto vfs_server rather than local
530
if not (backing_transport_server is None or \
531
isinstance(backing_transport_server, local.LocalURLServer)):
569
if not (backing_transport_server is None
570
or isinstance(backing_transport_server,
571
test_server.LocalURLServer)):
532
572
raise AssertionError(
533
573
"HTTPServer currently assumes local transport, got %s" % \
534
574
backing_transport_server)
554
594
self._http_starting.release()
558
"""See bzrlib.transport.Server.tearDown."""
559
self._httpd.tearDown()
597
def stop_server(self):
598
self._httpd.stop_server()
560
599
self._http_running = False
561
600
# We don't need to 'self._http_thread.join()' here since the thread is
562
601
# a daemonic one and will be garbage collected anyway. Joining just