Google App Engine 键值错误

2 投票
4 回答
1037 浏览
提问于 2025-04-16 00:17

我正在写一个谷歌应用引擎的应用程序,但在请求到达时出现了一个键值错误。

从错误追踪信息来看,我只是访问了一些内容,导致了这个键错误。

self.request.headers

完整的代码片段在这里,我只是转发了未修改的请求头。

     response = fetch( "%s%s?%s" % (
                                        self.getApiServer() ,
                                        self.request.path.replace("/twitter/", ""),
                                        self.request.query_string
                                    ),
                        self.request.body,
                        method,
                        self.request.headers,
                    )

处理请求的GET方法调用了proxy()。

# handle http get   
def get(self, *args):
    parameters = self.convertParameters(self.request.query_string)
    # self.prepareHeader("GET", parameters)
    self.request.query_string = "&".join("%s=%s" % (quote(key) , quote(value)) for key, value in parameters.items())
    self.proxy(GET, *args)
def convertParameters(self, source):
    parameters = {}
    for pairs in source.split("&"):
        item = pairs.split("=")
        if len(item) == 2:
            parameters[item[0]] = unquote(item[1])
    return parameters

错误的追踪信息如下:

'CONTENT_TYPE'
Traceback (most recent call last):
  File "/base/python_runtime/python_lib/versions/1/google/appengine/ext/webapp/__init__.py", line 513, in __call__
    handler.post(*groups)
  File "/base/data/home/apps/waytosing/1.342850593213842824/com/blogspot/zizon/twitter/RestApiProxy.py", line 67, in post
    self.proxy(POST, *args)
  File "/base/data/home/apps/waytosing/1.342850593213842824/com/blogspot/zizon/twitter/RestApiProxy.py", line 47, in proxy
    self.request.headers,
  File "/base/python_runtime/python_lib/versions/1/google/appengine/api/urlfetch.py", line 240, in fetch
    allow_truncated, follow_redirects)
  File "/base/python_runtime/python_lib/versions/1/google/appengine/api/urlfetch.py", line 280, in make_fetch_call
    for key, value in headers.iteritems():
  File "/base/python_runtime/python_dist/lib/python2.5/UserDict.py", line 106, in iteritems
    yield (k, self[k])
  File "/base/python_runtime/python_lib/versions/1/webob/datastruct.py", line 40, in __getitem__
    return self.environ[self._trans_name(item)]
KeyError: 'CONTENT_TYPE'

你知道为什么会发生这个错误吗?还是说这是一个已知的bug?

4 个回答

0

这是一个已知的问题,详细信息可以在这里找到:http://code.google.com/p/googleappengine/issues/detail?id=3427。另外,这里有一些可能的解决办法:http://code.google.com/p/googleappengine/issues/detail?id=2040

1

我对这个问题有一些观察:当内容类型是 application/x-www-form-urlencoded 而且 POST 数据为空(比如使用 jquery.ajax 的 GET 请求,或者 Twitter 的收藏和转发 API 等等),Google App Engine 会忽略这个内容类型。你可以在 urlfetch 之前添加:

self.request.headers.update({'content-type':'application/x-www-form-urlencoded'}) 

2

这看起来有点奇怪。文档提到,响应的“头部对象在你尝试获取或删除一个不存在的键时不会报错。获取一个不存在的头部只会返回 None”。不过从请求的文档来看,request.headers 是否也是这种类型的对象并不清楚,即使它们是普通的字典,iteritems 似乎也有点问题。所以这可能是个bug。

在调用 fetch 之前,检查一下 self.request.headers 可能是个好主意,看看 1) 它的实际类型是什么,2) 它的键都有哪些,3) 如果尝试获取 self.request.headers['CONTENT_TYPE'] 时是否会报错。

不过,如果你只是想解决问题并继续前进,可以尝试像这样绕过它:

if 'CONTENT_TYPE' not in self.request.headers:
    self.request.headers['CONTENT_TYPE'] = None

(我建议把它设置为 None,因为这就是一个响应头对象在键不存在时应该返回的结果)

撰写回答