summaryrefslogtreecommitdiff
path: root/paste/httpserver.py
diff options
context:
space:
mode:
Diffstat (limited to 'paste/httpserver.py')
-rwxr-xr-xpaste/httpserver.py76
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: