modified fcgi, hopefully works with py3
This commit is contained in:
@@ -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>'
|
||||||
|
|||||||
Reference in New Issue
Block a user