Index: third_party/httplib2/test/miniserver.py |
diff --git a/third_party/httplib2/test/miniserver.py b/third_party/httplib2/test/miniserver.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e32bf5e5f9bf59763623408baae5ef634c88d51b |
--- /dev/null |
+++ b/third_party/httplib2/test/miniserver.py |
@@ -0,0 +1,100 @@ |
+import logging |
+import os |
+import select |
+import SimpleHTTPServer |
+import SocketServer |
+import threading |
+ |
+HERE = os.path.dirname(__file__) |
+logger = logging.getLogger(__name__) |
+ |
+ |
+class ThisDirHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): |
+ def translate_path(self, path): |
+ path = path.split('?', 1)[0].split('#', 1)[0] |
+ return os.path.join(HERE, *filter(None, path.split('/'))) |
+ |
+ def log_message(self, s, *args): |
+ # output via logging so nose can catch it |
+ logger.info(s, *args) |
+ |
+ |
+class ShutdownServer(SocketServer.TCPServer): |
+ """Mixin that allows serve_forever to be shut down. |
+ |
+ The methods in this mixin are backported from SocketServer.py in the Python |
+ 2.6.4 standard library. The mixin is unnecessary in 2.6 and later, when |
+ BaseServer supports the shutdown method directly. |
+ """ |
+ |
+ def __init__(self, *args, **kwargs): |
+ SocketServer.TCPServer.__init__(self, *args, **kwargs) |
+ self.__is_shut_down = threading.Event() |
+ self.__serving = False |
+ |
+ def serve_forever(self, poll_interval=0.1): |
+ """Handle one request at a time until shutdown. |
+ |
+ Polls for shutdown every poll_interval seconds. Ignores |
+ self.timeout. If you need to do periodic tasks, do them in |
+ another thread. |
+ """ |
+ self.__serving = True |
+ self.__is_shut_down.clear() |
+ while self.__serving: |
+ r, w, e = select.select([self.socket], [], [], poll_interval) |
+ if r: |
+ self._handle_request_noblock() |
+ self.__is_shut_down.set() |
+ |
+ def shutdown(self): |
+ """Stops the serve_forever loop. |
+ |
+ Blocks until the loop has finished. This must be called while |
+ serve_forever() is running in another thread, or it will deadlock. |
+ """ |
+ self.__serving = False |
+ self.__is_shut_down.wait() |
+ |
+ def handle_request(self): |
+ """Handle one request, possibly blocking. |
+ |
+ Respects self.timeout. |
+ """ |
+ # Support people who used socket.settimeout() to escape |
+ # handle_request before self.timeout was available. |
+ timeout = self.socket.gettimeout() |
+ if timeout is None: |
+ timeout = self.timeout |
+ elif self.timeout is not None: |
+ timeout = min(timeout, self.timeout) |
+ fd_sets = select.select([self], [], [], timeout) |
+ if not fd_sets[0]: |
+ self.handle_timeout() |
+ return |
+ self._handle_request_noblock() |
+ |
+ def _handle_request_noblock(self): |
+ """Handle one request, without blocking. |
+ |
+ I assume that select.select has returned that the socket is |
+ readable before this function was called, so there should be |
+ no risk of blocking in get_request(). |
+ """ |
+ try: |
+ request, client_address = self.get_request() |
+ except socket.error: |
+ return |
+ if self.verify_request(request, client_address): |
+ try: |
+ self.process_request(request, client_address) |
+ except: |
+ self.handle_error(request, client_address) |
+ self.close_request(request) |
+ |
+ |
+def start_server(handler): |
+ httpd = ShutdownServer(("", 0), handler) |
+ threading.Thread(target=httpd.serve_forever).start() |
+ _, port = httpd.socket.getsockname() |
+ return httpd, port |