Python 如何从CGI脚本发送响应头和状态
我使用创建简单的CGI服务器。我希望我的CGI脚本在某些操作出错时处理响应代码。我该怎么做 我的CGI脚本中的代码片段Python 如何从CGI脚本发送响应头和状态,python,cgi,Python,Cgi,我使用创建简单的CGI服务器。我希望我的CGI脚本在某些操作出错时处理响应代码。我该怎么做 我的CGI脚本中的代码片段 if authmxn.authenticate(): stats = Stats() print "Content-Type: application/json" print 'Status: 200 OK' print print json.dumps(stats.getStats()) else: print
if authmxn.authenticate():
stats = Stats()
print "Content-Type: application/json"
print 'Status: 200 OK'
print
print json.dumps(stats.getStats())
else:
print 'Content-Type: application/json'
print 'Status: 403 Forbidden'
print
print json.dumps({'msg': 'request is not authenticated'})
请求处理程序中的一些代码段
def run_cgi(self):
'''
rest of code
'''
if not os.path.exists(scriptfile):
self.send_error(404, "No such CGI script (%s)" % `scriptname`)
return
if not os.path.isfile(scriptfile):
self.send_error(403, "CGI script is not a plain file (%s)" %
`scriptname`)
return
ispy = self.is_python(scriptname)
if not ispy:
if not (self.have_fork or self.have_popen2):
self.send_error(403, "CGI script is not a Python script (%s)" %
`scriptname`)
return
if not self.is_executable(scriptfile):
self.send_error(403, "CGI script is not executable (%s)" %
`scriptname`)
return
if not self.have_fork:
# Since we're setting the env in the parent, provide empty
# values to override previously set values
for k in ('QUERY_STRING', 'REMOTE_HOST', 'CONTENT_LENGTH',
'HTTP_USER_AGENT', 'HTTP_COOKIE'):
env.setdefault(k, "")
self.send_response(200, "Script output follows") # overrides the headers
decoded_query = query.replace('+', ' ')
使用标准库HTTP服务器,您无法执行此操作。从: 注意:CGIHTTPRequestHandler类运行的CGI脚本无法执行重定向(HTTP代码302),因为代码200(后面是脚本输出)是在执行CGI脚本之前发送的。这会优先使用状态代码 这意味着服务器不支持脚本中的
状态:
头。您正确地识别了代码中显示此支持不存在的部分:服务器甚至在运行脚本之前发送状态代码200。您无法在脚本中更改此设置
Python bugtracker中有几个与此相关的标签,有些带有补丁,请参见。因此,您可以选择修补标准库以添加此功能
但是,我强烈建议您切换到另一种技术而不是CGI(或运行真正的web服务器)。可以实现对覆盖HTTP状态行的
状态:代码消息
头的支持(HTTP响应的第一行,例如HTTP/1.0 200 OK
)。这需要:
cgihtprequesthandler
,以诱使其将CGI脚本的输出写入StringIO
对象,而不是直接写入套接字状态:
标题中提供的值更新HTTP状态行import BaseHTTPServer
import SimpleHTTPServer
from CGIHTTPServer import CGIHTTPRequestHandler
from cStringIO import StringIO
class BufferedCGIHTTPRequestHandler(CGIHTTPRequestHandler):
def setup(self):
"""
Arrange for CGI response to be buffered in a StringIO rather than
sent directly to the client.
"""
CGIHTTPRequestHandler.setup(self)
self.original_wfile = self.wfile
self.wfile = StringIO()
# prevent use of os.dup(self.wfile...) forces use of subprocess instead
self.have_fork = False
def run_cgi(self):
"""
Post-process CGI script response before sending to client.
Override HTTP status line with value of "Status:" header, if set.
"""
CGIHTTPRequestHandler.run_cgi(self)
self.wfile.seek(0)
headers = []
for line in self.wfile:
headers.append(line) # includes new line character
if line.strip() == '': # blank line signals end of headers
body = self.wfile.read()
break
elif line.startswith('Status:'):
# Use status header to override premature HTTP status line.
# Header format is: "Status: code message"
status = line.split(':')[1].strip()
headers[0] = '%s %s' % (self.protocol_version, status)
self.original_wfile.write(''.join(headers))
self.original_wfile.write(body)
def test(HandlerClass = BufferedCGIHTTPRequestHandler,
ServerClass = BaseHTTPServer.HTTPServer):
SimpleHTTPServer.test(HandlerClass, ServerClass)
if __name__ == '__main__':
test()
不用说,这可能不是最好的解决方案,您应该考虑非CGIHTTPServer解决方案,例如,一个微型框架,例如,一个合适的web服务器(从内存中,CGIHTTPServer不建议用于生产)、fastcgi或WSGI——仅举几个选项。实际上,问题是什么?你所拥有的似乎应该有用。你是说异常处理吗?(在这种情况下,您可以捕获异常并返回http响应代码500 internal server error。@mhawke您可以在上面的注释中查看上面的代码,您将看到它的重写头。您理解问题了吗?太好了……我可以使用WSCGI实现吗?twisted附带了一个内置的web服务器,可以使用
twistd运行。)-n web--路径。
当然,它可以在python中扩展: