diff options
Diffstat (limited to 'paste/httpserver.py')
-rwxr-xr-x | paste/httpserver.py | 76 |
1 files changed, 47 insertions, 29 deletions
diff --git a/paste/httpserver.py b/paste/httpserver.py index cd21713..179e526 100755 --- a/paste/httpserver.py +++ b/paste/httpserver.py @@ -17,16 +17,20 @@ if pyOpenSSL is installed, it also provides SSL capabilities. # @@: add support for chunked encoding, this is not a 1.1 server # till this is completed. +from __future__ import print_function import atexit import traceback -import socket, sys, threading, urlparse, Queue, urllib +import socket, sys, threading import posixpath +import six import time -import thread import os from itertools import count -from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer -from SocketServer import ThreadingMixIn +from six.moves import _thread +from six.moves import queue +from six.moves.BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer +from six.moves.socketserver import ThreadingMixIn +from six.moves.urllib.parse import unquote, urlsplit from paste.util import converters import logging try: @@ -38,6 +42,19 @@ except ImportError: __all__ = ['WSGIHandlerMixin', 'WSGIServer', 'WSGIHandler', 'serve'] __version__ = "0.5" + +def _get_headers(headers, k): + """ + Private function for abstracting differences in getting HTTP request + headers on Python 2 vs. Python 3 + """ + + if hasattr(headers, 'get_all'): + return headers.get_all(k) # Python 3 - email.message.Message + else: + return headers.getheaders(k) # Python 2 - mimetools.Message + + class ContinueHook(object): """ When a client request includes a 'Expect: 100-continue' header, then @@ -153,7 +170,7 @@ class WSGIHandlerMixin: if exc_info: try: if self.wsgi_headers_sent: - raise exc_info[0], exc_info[1], exc_info[2] + six.reraise(exc_info[0], exc_info[1], exc_info[2]) else: # In this case, we're going to assume that the # higher-level code is currently handling the @@ -176,8 +193,9 @@ class WSGIHandlerMixin: argument can be used to override any settings. """ - (scheme, netloc, path, query, fragment) = urlparse.urlsplit(self.path) - path = urllib.unquote(path) + dummy_url = 'http://dummy%s' % (self.path,) + (scheme, netloc, path, query, fragment) = urlsplit(dummy_url) + path = unquote(path) endslash = path.endswith('/') path = posixpath.normpath(path) if endslash and path != '/': @@ -244,14 +262,14 @@ class WSGIHandlerMixin: if hasattr(self.server, 'thread_pool'): # Now that we know what the request was for, we should # tell the thread pool what its worker is working on - self.server.thread_pool.worker_tracker[thread.get_ident()][1] = self.wsgi_environ + self.server.thread_pool.worker_tracker[_thread.get_ident()][1] = self.wsgi_environ self.wsgi_environ['paste.httpserver.thread_pool'] = self.server.thread_pool for k, v in self.headers.items(): key = 'HTTP_' + k.replace("-","_").upper() if key in ('HTTP_CONTENT_TYPE','HTTP_CONTENT_LENGTH'): continue - self.wsgi_environ[key] = ','.join(self.headers.getheaders(k)) + self.wsgi_environ[key] = ','.join(_get_headers(self.headers, k)) if hasattr(self.connection,'get_context'): self.wsgi_environ['wsgi.url_scheme'] = 'https' @@ -293,7 +311,7 @@ class WSGIHandlerMixin: if hasattr(result,'close'): result.close() result = None - except socket.error, exce: + except socket.error as exce: self.wsgi_connection_drop(exce, environ) return except: @@ -390,7 +408,7 @@ else: return (conn, info) def _auto_ssl_context(): - import OpenSSL, time, random + import OpenSSL, random pkey = OpenSSL.crypto.PKey() pkey.generate_key(OpenSSL.crypto.TYPE_RSA, 768) @@ -439,7 +457,7 @@ class WSGIHandler(WSGIHandlerMixin, BaseHTTPRequestHandler): # don't bother logging disconnects while handling a request try: BaseHTTPRequestHandler.handle(self) - except SocketErrors, exce: + except SocketErrors as exce: self.wsgi_connection_drop(exce) def address_string(self): @@ -575,12 +593,12 @@ class ThreadPool(object): self.nworkers = nworkers self.max_requests = max_requests self.name = name - self.queue = Queue.Queue() + self.queue = queue.Queue() self.workers = [] self.daemon = daemon if logger is None: logger = logging.getLogger('paste.httpserver.ThreadPool') - if isinstance(logger, basestring): + if isinstance(logger, six.string_types): logger = logging.getLogger(logger) self.logger = logger self.error_email = error_email @@ -734,7 +752,7 @@ class ThreadPool(object): return thread_id in threading._active def add_worker_thread(self, *args, **kwargs): - index = self._worker_count.next() + index = six.next(self._worker_count) worker = threading.Thread(target=self.worker_thread_callback, args=args, kwargs=kwargs, name=("worker %d" % index)) @@ -777,7 +795,7 @@ class ThreadPool(object): import pprint info_desc = pprint.pformat(info) except: - out = StringIO() + out = six.StringIO() traceback.print_exc(file=out) info_desc = 'Error:\n%s' % out.getvalue() self.notify_problem( @@ -839,7 +857,7 @@ class ThreadPool(object): ids="\n ".join(map(str, found))), subject="Process restart (too many zombie threads)") self.shutdown(10) - print 'Shutting down', threading.currentThread() + print('Shutting down', threading.currentThread()) raise ServerExit(3) def worker_thread_callback(self, message=None): @@ -848,7 +866,7 @@ class ThreadPool(object): callables. """ thread_obj = threading.currentThread() - thread_id = thread_obj.thread_id = thread.get_ident() + thread_id = thread_obj.thread_id = _thread.get_ident() self.workers.append(thread_obj) self.idle_workers.append(thread_id) requests_processed = 0 @@ -880,8 +898,8 @@ class ThreadPool(object): # removing all remnants of any exception, so # we should log it now. But ideally no # exception should reach this level - print >> sys.stderr, ( - 'Unexpected exception in worker %r' % runnable) + print('Unexpected exception in worker %r' % runnable, + file=sys.stderr) traceback.print_exc() if thread_id in self.dying_threads: # That last exception was intended to kill me @@ -891,7 +909,8 @@ class ThreadPool(object): del self.worker_tracker[thread_id] except KeyError: pass - sys.exc_clear() + if six.PY2: + sys.exc_clear() self.idle_workers.append(thread_id) finally: try: @@ -939,15 +958,14 @@ class ThreadPool(object): self.kill_worker(worker.thread_id) self.logger.info('Workers killed forcefully') if force_quit_timeout: - hung = [] timed_out = False need_force_quit = bool(zombies) - for workers in self.workers: + for worker in self.workers: if not timed_out and worker.isAlive(): timed_out = True worker.join(force_quit_timeout) if worker.isAlive(): - print "Worker %s won't die" % worker + print("Worker %s won't die" % worker) need_force_quit = True if need_force_quit: import atexit @@ -961,7 +979,7 @@ class ThreadPool(object): if mod == 'threading': atexit._exithandlers.remove(callback) atexit._run_exitfuncs() - print 'Forcefully exiting process' + print('Forcefully exiting process') os._exit(3) else: self.logger.info('All workers eventually killed') @@ -1020,7 +1038,7 @@ class ThreadPool(object): if e.strip()] server.sendmail(from_address, error_emails, message) server.quit() - print 'email sent to', error_emails, message + print('email sent to', error_emails, message) class ThreadPoolMixIn(object): """ @@ -1301,10 +1319,10 @@ def serve(application, host=None, port=None, handler=None, ssl_pem=None, protocol = is_ssl and 'https' or 'http' host, port = server.server_address[:2] if host == '0.0.0.0': - print 'serving on 0.0.0.0:%s view at %s://127.0.0.1:%s' % \ - (port, protocol, port) + print('serving on 0.0.0.0:%s view at %s://127.0.0.1:%s' + % (port, protocol, port)) else: - print "serving on %s://%s:%s" % (protocol, host, port) + print("serving on %s://%s:%s" % (protocol, host, port)) try: server.serve_forever() except KeyboardInterrupt: |