modified fcgi, hopefully works with py3

This commit is contained in:
mdipierro
2020-03-22 14:06:25 -07:00
parent e004215ea6
commit fa6e9b1caf
+31 -25
View File
@@ -44,16 +44,18 @@ See the documentation for WSGIServer/Server for more information.
On most platforms, fcgi will fallback to regular CGI behavior if run in a On most platforms, fcgi will fallback to regular CGI behavior if run in a
non-FastCGI context. If you want to force CGI behavior, set the environment non-FastCGI context. If you want to force CGI behavior, set the environment
variable FCGI_FORCE_CGI to "Y" or "y". variable FCGI_FORCE_CGI to "Y" or "y".
Modified for web2py
""" """
__author__ = 'Allan Saddi <allan@saddi.com>' __author__ = 'Allan Saddi <allan@saddi.com>'
__version__ = '$Revision$' __version__ = '$Revision$'
import cgi
import sys import sys
import os import os
import signal import signal
import struct import struct
import cStringIO as StringIO
import select import select
import socket import socket
import errno import errno
@@ -68,6 +70,15 @@ except ImportError:
import dummy_threading as threading import dummy_threading as threading
thread_available = False thread_available = False
is_py2 = sys.version_info[0] == 2
if is_py2:
from cgi import escape
import cStringIO as StringIO
else:
from io import StringIO
from html import escape
# Apparently 2.3 doesn't define SHUT_WR? Assume it is 1 in this case. # Apparently 2.3 doesn't define SHUT_WR? Assume it is 1 in this case.
if not hasattr(socket, 'SHUT_WR'): if not hasattr(socket, 'SHUT_WR'):
socket.SHUT_WR = 1 socket.SHUT_WR = 1
@@ -234,11 +245,9 @@ class InputStream(object):
total += len(line) total += len(line)
if 0 < sizehint <= total: if 0 < sizehint <= total:
break break
line = self.readline() yield self.readline()
return lines
def __iter__(self): __iter__ = readlines
return self
def next(self): def next(self):
r = self.readline() r = self.readline()
@@ -592,7 +601,7 @@ class Request(object):
self._flush() self._flush()
self._end(appStatus, protocolStatus) self._end(appStatus, protocolStatus)
def _end(self, appStatus=0L, protocolStatus=FCGI_REQUEST_COMPLETE): def _end(self, appStatus=0, protocolStatus=FCGI_REQUEST_COMPLETE):
self._conn.end_request(self, appStatus, protocolStatus) self._conn.end_request(self, appStatus, protocolStatus)
def _flush(self): def _flush(self):
@@ -615,7 +624,7 @@ class CGIRequest(Request):
self.stderr = sys.stderr self.stderr = sys.stderr
self.data = StringIO.StringIO() self.data = StringIO.StringIO()
def _end(self, appStatus=0L, protocolStatus=FCGI_REQUEST_COMPLETE): def _end(self, appStatus=0, protocolStatus=FCGI_REQUEST_COMPLETE):
sys.exit(appStatus) sys.exit(appStatus)
def _flush(self): def _flush(self):
@@ -664,7 +673,7 @@ class Connection(object):
self.process_input() self.process_input()
except EOFError: except EOFError:
break break
except (select.error, socket.error), e: except (select.error, socket.error) as e:
if e.errno == errno.EBADF: # Socket was closed by Request. if e.errno == errno.EBADF: # Socket was closed by Request.
break break
raise raise
@@ -714,7 +723,7 @@ class Connection(object):
""" """
rec.write(self._sock) rec.write(self._sock)
def end_request(self, req, appStatus=0L, def end_request(self, req, appStatus=0,
protocolStatus=FCGI_REQUEST_COMPLETE, remove=True): protocolStatus=FCGI_REQUEST_COMPLETE, remove=True):
""" """
End a Request. End a Request.
@@ -763,7 +772,7 @@ class Connection(object):
if not self._multiplexed and self._requests: if not self._multiplexed and self._requests:
# Can't multiplex requests. # Can't multiplex requests.
self.end_request(req, 0L, FCGI_CANT_MPX_CONN, remove=False) self.end_request(req, 0, FCGI_CANT_MPX_CONN, remove=False)
else: else:
self._requests[inrec.requestId] = req self._requests[inrec.requestId] = req
@@ -854,7 +863,7 @@ class MultiplexedConnection(Connection):
finally: finally:
self._lock.release() self._lock.release()
def end_request(self, req, appStatus=0L, def end_request(self, req, appStatus=0,
protocolStatus=FCGI_REQUEST_COMPLETE, remove=True): protocolStatus=FCGI_REQUEST_COMPLETE, remove=True):
self._lock.acquire() self._lock.acquire()
try: try:
@@ -949,8 +958,7 @@ class Server(object):
this keyword is ignored; it's not possible to multiplex requests this keyword is ignored; it's not possible to multiplex requests
at all. at all.
""" """
if handler is not None: self.handler = handler or self.default_handler
self.handler = handler
self.maxwrite = maxwrite self.maxwrite = maxwrite
if thread_available: if thread_available:
try: try:
@@ -1077,7 +1085,7 @@ class Server(object):
while self._keepGoing: while self._keepGoing:
try: try:
r, w, e = select.select([sock], [], [], timeout) r, w, e = select.select([sock], [], [], timeout)
except select.error, e: except select.error as e:
if e.errno == errno.EINTR: if e.errno == errno.EINTR:
continue continue
raise raise
@@ -1125,13 +1133,13 @@ class Server(object):
self._keepGoing = False self._keepGoing = False
self._hupReceived = reload self._hupReceived = reload
def handler(self, req): def default_handler(self, req):
""" """
Default handler, which just raises an exception. Unless a handler Default handler, which just raises an exception. Unless a handler
is passed at initialization time, this must be implemented by is passed at initialization time, this must be implemented by
a subclass. a subclass.
""" """
raise NotImplementedError, self.__class__.__name__ + '.handler' raise NotImplementedError(self.__class__.__name__ + '.handler')
def error(self, req): def error(self, req):
""" """
@@ -1147,8 +1155,7 @@ class WSGIServer(Server):
FastCGI server that supports the Web Server Gateway Interface. See FastCGI server that supports the Web Server Gateway Interface. See
<http://www.python.org/peps/pep-0333.html>. <http://www.python.org/peps/pep-0333.html>.
""" """
def __init__(self, application, environ=None, def __init__(self, application, environ=None, multithreaded=True, **kw):
multithreaded=True, **kw):
""" """
environ, if present, must be a dictionary-like object. Its environ, if present, must be a dictionary-like object. Its
contents will be copied into application's environ. Useful contents will be copied into application's environ. Useful
@@ -1156,7 +1163,7 @@ class WSGIServer(Server):
Set multithreaded to False if your application is not MT-safe. Set multithreaded to False if your application is not MT-safe.
""" """
if kw.has_key('handler'): if 'handler'in kw:
del kw['handler'] # Doesn't make sense to let this through del kw['handler'] # Doesn't make sense to let this through
super(WSGIServer, self).__init__(**kw) super(WSGIServer, self).__init__(**kw)
@@ -1170,7 +1177,7 @@ class WSGIServer(Server):
# Used to force single-threadedness # Used to force single-threadedness
self._app_lock = thread.allocate_lock() self._app_lock = thread.allocate_lock()
def handler(self, req): def default_handler(self, req):
"""Special handler for WSGI.""" """Special handler for WSGI."""
if req.role != FCGI_RESPONDER: if req.role != FCGI_RESPONDER:
return FCGI_UNKNOWN_ROLE, 0 return FCGI_UNKNOWN_ROLE, 0
@@ -1240,7 +1247,7 @@ class WSGIServer(Server):
try: try:
if headers_sent: if headers_sent:
# Re-raise if too late # Re-raise if too late
raise exc_info[0], exc_info[1], exc_info[2] raise exc_info[0](exc_info[1], exc_info[2])
finally: finally:
exc_info = None # avoid dangling circular ref exc_info = None # avoid dangling circular ref
else: else:
@@ -1304,7 +1311,6 @@ class WSGIServer(Server):
if __name__ == '__main__': if __name__ == '__main__':
def test_app(environ, start_response): def test_app(environ, start_response):
"""Probably not the most efficient example.""" """Probably not the most efficient example."""
import cgi
start_response('200 OK', [('Content-Type', 'text/html')]) start_response('200 OK', [('Content-Type', 'text/html')])
yield '<html><head><title>Hello World!</title></head>\n' \ yield '<html><head><title>Hello World!</title></head>\n' \
'<body>\n' \ '<body>\n' \
@@ -1313,10 +1319,10 @@ if __name__ == '__main__':
names = environ.keys() names = environ.keys()
names.sort() names.sort()
for name in names: for name in names:
yield '<tr><td>%s</td><td>%s</td></tr>\n' % ( yield '<tr><td>%s</td><td>%s</td></tr>\n' % (name, escape(environ[name]))
name, cgi.escape(`environ[name]`))
form = cgi.FieldStorage(fp=environ['wsgi.input'], environ=environ, form = cgi.FieldStorage(fp=environ['wsgi.input'],
environ=environ,
keep_blank_values=1) keep_blank_values=1)
if form.list: if form.list:
yield '<tr><th colspan="2">Form data</th></tr>' yield '<tr><th colspan="2">Form data</th></tr>'