这里测试服务器是这样的作品,虽然它是相当丑陋和一种缓慢的解决方案。它需要为每个要运行的CGI脚本单独提供一个CGIApplication
对象。所以如果你有一个完整的目录,你需要实例化一个不同的CGIApplication
对象。当你实例化它时,当然取决于你。您可以选择为每个请求实例化新的请求,但如果以某种方式避免这种情况,您可能会节省一些时间。
import os
import os.path as _osp
import re
import subprocess
import io
import email.parser
env_forward = re.compile('^[A-Z][A-Z0-9_]*$')
header_match = re.compile(b'^(.*?\\n[ \\t\\r]*\\n)(.*)$', re.M | re.S)
env_whitelist = frozenset(('AUTH_TYPE', 'CONTENT_LENGTH', 'CONTENT_TYPE',
'DOCUMENT_ROOT', 'QUERY_STRING', 'PATH_INFO',
'PATH_TRANSLATED', 'REMOTE_ADDR', 'REMOTE_PORT',
'REMOTE_IDENT', 'REMOTE_USER', 'REQUEST_METHOD',
'REQUEST_URI', 'SCRIPT_NAME',
'SERVER_ADDR', 'SERVER_ADMIN', 'SERVER_NAME',
'SERVER_PORT', 'SERVER_PROTOCOL',
'SERVER_SIGNATURE', 'SERVER_SOFTWARE'))
class CGIApplication(object):
def __init__(self, appfname):
self._appfname = _osp.abspath(appfname)
def __call__(self, environ, start_respose):
appenv = {item[0]: item[1] \
for item in environ.items() \
if ((item[0] in env_whitelist) or
item[0].startswith('HTTP_'))}
appenv['GATEWAY_INTERFACE'] = 'CGI/1.1'
appenv['PATH'] = '/usr/local/bin:/usr/bin:/bin'
appenv['SCRIPT_FILENAME'] = self._appfname
nbytes_for_cgi = appenv.get('CONTENT_LENGTH', '')
nbytes_for_cgi = (int(nbytes_for_cgi) if nbytes_for_cgi != '' else 0)
args = [self._appfname]
query = environ.get('QUERY_STRING', None)
query = query.replace('+', ' ')
if '=' not in query:
args.append(query)
proc = subprocess.Popen(args,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
env = appenv,
cwd = _osp.dirname(self._appfname))
bytes_read = 0
data_for_cgi = io.BytesIO()
while bytes_read < nbytes_for_cgi:
data = environ['wsgi.input'].read(nbytes_for_cgi - bytes_read)
bytes_read += len(data)
data_for_cgi.write(data)
data = None
data_for_cgi = data_for_cgi.getvalue()
output, errdata = proc.communicate(data_for_cgi)
data_for_cgi = None
proc.stdin.close()
proc.stdout.close()
proc.stderr.close()
try:
errdata = errdata.decode('utf-8')
except UnicodeDecodeError:
errdata = errdata.decode('iso8859-1')
environ['wsgi.errors'].write(errdata)
errdata = None
if proc.returncode != 0:
start_respose('500 Internal Server Error',
[('Content-Type', 'text/plain')])
return (b"CGI application died with non-zero return code.\n",)
else:
output_hdr = header_match.match(output)
output_hdr, output = output_hdr.groups()
parser = email.parser.HeaderParser()
headers = parser.parsestr(output_hdr.decode('iso8859-1'))
status = headers.get_all('Status', ['200 OK'])[-1]
del headers['Status']
start_respose(status, list(headers.items()))
return (output,)
这可能是一个容易得多,刚刚成立的httpd已经做了你所需要的一个小的配置文件。 – 2012-03-05 19:43:29
@ IgnacioVazquez-Abrams - 我不明白那会怎么简单。阿帕奇一直像是一个非常痛苦的野兽去跑步。我所做过的所有网络应用都令人愉快,只有一个微型Web服务器可以用于开发。 – Omnifarious 2012-03-05 20:10:12
如果配置Apache是问题,您可能需要尝试[xampp](http://www.apachefriends.org/en/xampp.html)。 – 2012-03-06 04:12:08