我有python服务器提供cgi脚本,
我想在状态代码中添加状态代码。我做了,
try:
cgi = CGI()
output = cgi.fire()
print 'Content-Type text/json'
print 'Status:200 success'
print
print json.dumps(output)
except:
print 'Content-Type: text/json'
print 'Status: 403 Forbidden'
print
print json.dumps({'msg':'error'})
但是当我通过dojo xhr请求请求这个脚本时,我得到了200个请求状态。为什么会这样?
Request URL:http://192.168.2.72:8080/cgi-bin/cgi.py
Request Method:POST
Status Code:200 Script output follows
Request Headersview source
Accept:*/*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Cache-Control:no-cache
Connection:keep-alive
Content-Length:125
Content-Type:application/x-www-form-urlencoded
Host:192.168.2.72:7999
Origin:http://192.168.2.72:7999
Pragma:no-cache
Referer:http://192.168.2.72:7999/home.html
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.22 (KHTML, like Gecko) Ubuntu Chromium/25.0.1364.160 Chrome/25.0.1364.160 Safari/537.22
X-Requested-With:XMLHttpRequest
Form Dataview sourceview URL encoded
Response Headersview source
Content-Type:text/json
Date:Fri, 08 Aug 2014 05:16:29 GMT
Server:SimpleHTTP/0.6 Python/2.7.3
Status:403 Forbidden
任何输入?
我已经尝试过的事情:
result.ioArgs.xhr.getAllResponseHeaders() // returns string
ioargs.xhr.status // returns the request status.
答案 0 :(得分:6)
如果json.dumps(output)
引发异常,您已经打印了包含状态代码(通常拼写为Status: 200 OK
)的标题和一个空行以结束HTTP响应的标题部分。< / p>
然后,except
块将打印第二组标题,但那些实际上被认为是该点响应主体的一部分,因为打印空行结束了标题。请参阅HTTP message规范。
解决方案是等到你知道打印任何标题的输出是什么。
<强> - 更多 - 强>
如果您为其提供不可序列化的输入, json.dumps
可能会引发异常。鉴于cgi.fire()
似乎是某个自定义CGI对象的方法(内置cgi
模块没有该方法),它可能会返回任何内容。
要进行调试,您需要记录引发的异常,最好使用回溯。您所拥有的except:
块将会捕获所有错误,然后不对它们执行任何操作,因此您不知道发生了什么,也没有人查看该问题。您可能还需要记录output
的值。
答案 1 :(得分:2)
为了补充Jason S所说的我在his answer中完全复制的内容,我使用非json可序列化对象(在此示例中为md5哈希)再现了完全相同的故障,并且具有与原始海报相同的行为200返回代码
#!/usr/bin/env python
import json
import traceback
class CGI:
def fire(self):
import md5
return md5.md5()
try:
cgi = CGI()
output = cgi.fire()
print 'Content-Type text/json'
print 'Status:200 success'
print
print json.dumps(output)
except:
traceback.print_exc()
print 'Content-Type: text/json'
print 'Status: 403 Forbidden'
print
print json.dumps({'msg':'error'})
与服务器交互
$ socat - TCP4:localhost:8000
输入
GET /cgi-bin/test.py HTTP/1.0
输出
HTTP/1.0 200 Script output follows
Server: SimpleHTTP/0.6 Python/3.4.0
Date: Sun, 17 Aug 2014 16:16:19 GMT
Content-Type text/json
Status:200 success
Content-Type: text/json
Status: 403 Forbidden
{"msg": "error"}
回溯:
127.0.0.1 - - [17/Aug/2014 18:16:19] "GET /cgi-bin/test.py HTTP/1.0" 200 -
Traceback (most recent call last):
File "/home/xcombelle/dev/test/cgi-bin/test.py", line 16, in <module>
print json.dumps(output)
File "/usr/lib/python2.7/json/__init__.py", line 231, in dumps
return _default_encoder.encode(obj)
File "/usr/lib/python2.7/json/encoder.py", line 200, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/usr/lib/python2.7/json/encoder.py", line 263, in iterencode
return _iterencode(o, 0)
File "/usr/lib/python2.7/json/encoder.py", line 177, in default
raise TypeError(repr(o) + " is not JSON serializable")
TypeError: <md5 HASH object @ 0x7fcb090d0a30> is not JSON serializable
答案 2 :(得分:1)
在输出标题之前,只需将json.dumps()转换为字符串,你应该没问题吗?
这将保护您不会设置标题,然后在打印时异常获得异常
答案 3 :(得分:1)
对于将来遇到此问题的任何人,其原因是用于提供内容的 python http.server。出于某种原因,这被设计为在 cgi 脚本开始运行之前吐出一个 Status 200: script output follows
标头。这意味着您无法更改脚本中返回的状态代码(请参阅 this page 上的 CGIHTTPRequestHandler 文档)
这实际上使开发时使用起来非常痛苦,因为错误不会以与生产中相同的方式传播。
答案 4 :(得分:-2)
我认为您正在设置Status:
标题字段,但您想设置Status-Code:
。
您的脚本是否真的将Status Code:200 Script output follows
写为标题字段?