Commit 8c4a6620 authored by Denis Bilenko's avatar Denis Bilenko

make pywsgi use server.StreamServer

parent 68f74a4e
...@@ -22,20 +22,17 @@ ...@@ -22,20 +22,17 @@
# THE SOFTWARE. # THE SOFTWARE.
import errno import errno
import os
import sys import sys
import time import time
import traceback import traceback
from urllib import unquote from urllib import unquote
from gevent import socket, sleep from gevent import socket
import BaseHTTPServer import BaseHTTPServer
from gevent.pool import Pool import gevent
from gevent.greenlet import Greenlet from gevent.server import StreamServer
DEFAULT_MAX_SIMULTANEOUS_REQUESTS = 1024
DEFAULT_MAX_HTTP_VERSION = 'HTTP/1.1'
MAX_REQUEST_LINE = 8192 MAX_REQUEST_LINE = 8192
...@@ -144,9 +141,6 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler): ...@@ -144,9 +141,6 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
protocol_version = 'HTTP/1.1' protocol_version = 'HTTP/1.1'
def handle_one_request(self): def handle_one_request(self):
if self.server.max_http_version:
self.protocol_version = self.server.max_http_version
if self.rfile.closed: if self.rfile.closed:
self.close_connection = 1 self.close_connection = 1
return return
...@@ -171,7 +165,7 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler): ...@@ -171,7 +165,7 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
return return
self.environ = self.get_environ() self.environ = self.get_environ()
self.application = self.server.app self.application = self.server.application
try: try:
self.handle_one_response() self.handle_one_response()
except socket.error, e: except socket.error, e:
...@@ -326,105 +320,36 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler): ...@@ -326,105 +320,36 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
self.connection.close() self.connection.close()
class Server(BaseHTTPServer.HTTPServer): class WSGIServer(StreamServer):
def __init__(self, socket, address, app, log=None, environ=None, max_http_version=None, protocol=HttpProtocol):
self.outstanding_requests = 0
self.socket = socket
self.address = address
if log:
self.log = log
else:
self.log = sys.stderr
self.app = app
self.environ = environ
self.max_http_version = max_http_version
self.protocol = protocol
self.pid = os.getpid()
def get_environ(self):
d = {
'wsgi.errors': sys.stderr,
'wsgi.version': (1, 0),
'wsgi.multithread': True,
'wsgi.multiprocess': False,
'wsgi.run_once': False,
'wsgi.url_scheme': 'http',
}
if self.environ is not None:
d.update(self.environ)
return d
def process_request(self, (socket, address)):
proto = self.protocol(socket, address, self)
proto.handle()
def log_message(self, message):
self.log.write(message + '\n')
def server(sock, site, log=None, environ=None, max_size=None, max_http_version=DEFAULT_MAX_HTTP_VERSION,
protocol=HttpProtocol):
serv = Server(sock, sock.getsockname(), site, log, environ=None,
max_http_version=max_http_version, protocol=protocol)
if max_size is None:
max_size = DEFAULT_MAX_SIMULTANEOUS_REQUESTS
pool = Pool(size=max_size)
try:
host, port = sock.getsockname()
port = ':%s' % (port, )
if hasattr(sock, 'do_handshake'):
scheme = 'https'
if port == ':443':
port = ''
else:
scheme = 'http'
if port == ':80':
port = ''
print "(%s) wsgi starting up on %s://%s%s/" % (os.getpid(), scheme, host, port)
delay = 0.1
while True:
try:
client_socket = sock.accept()
delay = 0.1
pool.spawn(serv.process_request, client_socket)
except socket.error, e:
if e[0] == errno.EMFILE:
print "WARNING: pywsgi: out of file descriptors; will not accept for %s seconds" % delay
else:
print 'WARNING: pywsgi: accept failed with error %s: %s; will not accept for %s seconds' % (e[0], e, delay)
sleep(delay)
delay *= 2
finally:
try:
sock.close()
except Exception:
pass
# compatibilty with wsgi module, for tests handler_class = HttpProtocol
class WSGIServer(object): base_env = {'GATEWAY_INTERFACE': 'CGI/1.1',
'SERVER_SOFTWARE': 'gevent/%d.%d Python/%d.%d' % (gevent.version_info[:2] + sys.version_info[:2]),
'SCRIPT_NAME': '',
'wsgi.version': (1, 0),
'wsgi.url_scheme': 'http',
'wsgi.errors': sys.stderr,
'wsgi.multithread': False,
'wsgi.multiprocess': False,
'wsgi.run_once': False}
def __init__(self, address, application): def __init__(self, listener, application, backlog=None, pool=None, handler_class=None, log=sys.stderr, **ssl_args):
self.address = address StreamServer.__init__(self, listener, backlog=backlog, pool=pool, log=log)
if hasattr(listener, 'do_handshake'):
self.base_env['wsgi.url_scheme'] = 'https'
self.application = application self.application = application
@property def get_environ(self):
def server_port(self): return self.base_env.copy()
return self.address[1]
def pre_start(self):
def start(self): StreamServer.pre_start(self)
self.socket = socket.tcp_listener(self.address) env = self.base_env.copy()
self.address = self.socket.getsockname() env.update( {'SERVER_NAME': socket.getfqdn(self.server_host),
self.server = Greenlet.spawn(server, self.socket, self.application) 'SERVER_PORT': str(self.server_port) } )
self.base_env = env
def stop(self):
self.server.kill(KeyboardInterrupt) def handle(self, socket, address):
self.socket.close() handler = self.handler_class(socket, address, self)
self.server.join() handler.handle()
def serve_forever(self):
self.start()
self.server.join()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment