解决httputil.HTTPInputError("Response code %d cannot have body" % code)在tornado出现报错
问题原因
tornado出现httputil.HTTPInputError("Response code %d cannot have body" % code)
的原因是HTTP状态码为405、406、408、411、413、415、501或505时,tornado认为其响应体不应该被返回,因为这些状态码通常表示请求有误或服务器无法处理。
为了避免这个错误,可以在处理请求时检查返回的状态码,如果是上述提到的状态码之一,确保不返回响应体即可。可以通过捕获httputil.HTTPInputError
异常并在相应的处理逻辑中处理这种情况。
以下是一个处理HTTP状态码为405的示例代码:
import tornado.web
from tornado import httputil
class MainHandler(tornado.web.RequestHandler):
def post(self):
try:
# 处理POST请求
if some_condition:
self.set_status(405) # 设置状态码为405
self.finish() # 结束响应,不返回响应体
except httputil.HTTPInputError as e:
self.set_status(e.status_code) # 设置错误状态码
self.finish() # 结束响应,不返回响应体
通过以上示例代码,可以在处理POST请求时,如果满足某条件,设置状态码为405并结束响应,避免出现tornado.httputil.HTTPInputError("Response code 405 cannot have body")
错误。
解决方案
httputil.HTTPInputError("Response code %d cannot have body" % code)
错误是由于 Tornado 在处理 HTTP 请求时,遇到了一个不能包含响应体的响应状态码(如 204 No Content,304 Not Modified 等)却收到了响应体导致的异常。
要解决这个问题,可以采取以下几种方法:
1. 确保服务器端返回的响应状态码与 HTTP 协议规范相符,不应该在不允许有响应体的状态码中返回响应体。
2. 在客户端处理这种异常情况时,可以捕获 httputil.HTTPInputError
异常,并针对性地处理,比如跳过读取响应体的步骤。
3. 如果是在使用 Tornado 的 HTTPClient
进行请求时出现这个问题,可以在发起请求时设置 allow_nonstandard_methods=True
,这样就允许不标准的 HTTP 方法和状态码了。例如:
client = httpclient.HTTPClient()
try:
response = client.fetch("http://example.com", method="SOME_NON_STANDARD_METHOD", allow_nonstandard_methods=True)
# 处理响应
except httputil.HTTPInputError as e:
print("HTTPInputError:", e)
finally:
client.close()
通过以上方法的合理运用,可以解决 Tornado 出现 httputil.HTTPInputError("Response code %d cannot have body" % code)
的问题。
具体例子
httputil.HTTPInputError("Response code %d cannot have body" % code)
这个错误表示在收到指定的响应代码时尝试读取正文(body)时出错。一般来说,对于一些特定的响应代码,如 204 No Content,303 See Other 等,根据 HTTP 规范是不应该包含正文的。因此,当试图读取这些响应的正文时,就会触发该错误。
为了正确处理这个错误,你可以在尝试读取响应正文之前,先检查响应的状态码,如果是对应不应该包含正文的响应代码,就不要尝试读取正文。
以下是一个使用 tornado 的示例代码,演示了如何正确处理 httputil.HTTPInputError
错误:
import tornado.ioloop
import tornado.web
from tornado import httpclient
from tornado import httputil
async def fetch_data():
http_client = httpclient.AsyncHTTPClient()
try:
response = await http_client.fetch("https://www.example.com")
if response.code == 204 or response.code == 303:
# 对于 204 No Content 和 303 See Other,不尝试读取正文
print("Response code %d cannot have body" % response.code)
else:
body = response.body
print(body)
except httputil.HTTPInputError as e:
print("Caught HTTPInputError:", e)
if __name__ == "__main__":
tornado.ioloop.IOLoop.current().run_sync(fetch_data)
在这个示例中,我们先尝试获取一个网址的响应,然后根据响应的状态码来决定是否读取响应正文。如果状态码是 204 或 303,就不尝试读取正文,并打印提示信息;如果遇到 httputil.HTTPInputError
错误,则捕获该错误并打印相应的错误信息。
通过以上代码示例,我们可以正确处理 httputil.HTTPInputError
错误,并根据实际情况决定是否读取 HTTP 响应的正文。