如何在请求(或urllib3.response)中获取完整的服务器响应消息?

时间:2018-09-17 14:48:43

标签: python-requests httpresponse urllib3

最近几天,我在使用Google Sheet API时遇到了问题,我可以从请求(通过requests_oauthlib扩展名)获得的所有响应消息都是标头&400 Bad Request。请求版本为2.19.1。这发生在多个端点(v4)上,例如spreadsheets.values.appendspreadsheets.values.batchUpdatespreadsheets.values.update等。

我浪费了很多时间来确保我没有形成正确的数据结构,直到那时我才意识到我没有从API服务器获得整个响应消息。

似乎从requests.Response返回的r = request.Request('https://httpbin.org')对象来自requests.HTTPAdapter对象,而该对象又是urllib3.response.HTTPResponse的包装。因此,我尝试使用r.reasonr.raw._original_responser.raw._bodyr.raw.msg,除了对象引用和None(或者只是空字符串)之外,它什么都没有给我

长话短说,我放弃了一会儿,回到它之后,我意识到我应该尝试使用我一直忽略的Google API Explorer,结果发现 is 响应中出现错误消息,并且400错误不是由于任何无效的有效负载/数据结构形式引起的。

{   "error": {
    "code": 400,
    "message": "Invalid data[0]: Requested writing within range [mysheet!A3:AH3], but tried writing to row [4]",
    "status": "INVALID_ARGUMENT"   } 
}

我的问题是:

我在如何调试请求的连接响应中是否出错?实际上有一种方法可以从请求中从服务器获取完整的原始消息,例如curl中的完整调试模式?还是仅在API请求来自Google API资源管理器时才发送此消息?

2 个答案:

答案 0 :(得分:1)

我从a closed issue in requests repo发布的去年发现westover的标题为“建议:提高身份的提高,以包括响应机构(如果有的话)”,他在其中写道:

  

查找有关HTTPError异常的更多详细信息。我正在使用的API发送回400,但其中也包含text / json正文。如果raise_for_status()函数包含响应文本(如果有的话),那就太好了。

他还提供了一些变通方法功能,成为讨论进入a pull request discussion的原因的基础:

import requests
from requests.exceptions import HTTPError
def expanded_raise_for_status(res):
    """
    Take a "requests" response object and expand the raise_for_status method to return more helpful errors
    @param res:
    @return: None
    """
    try:
        res.raise_for_status()
    except HTTPError as e:
        if res.text:
            raise HTTPError('{} Error Message: {}'.format(str(e.message), res.text))
        else:
           raise e
    return

我在现有类中采用了此方法,并且基本上是jwodder所指出的,它扩展/劫持Response.raise_for_status()方法,只要用户使用raise_for_status()时就会调用HTTPError(RequestsException)类从服务器响应提供错误消息,通常形式为assert response.status_code == 200, raise_for_status()。这是通过在异常消息中添加Response.text(或content / json方法)并返回响应主体来实现的,而不是将当前代码返回<self.status_code, self.reason, self.url>转换为{{ 1}}。

400 Bad Requests <url>

(在this reply中,他进一步阐述了他认为该功能值得的原因,但请求请求被拒绝,并且我认为维护者也有很好的意思),这可能导致其他异常或更多鉴于该模块的普及程度以及使用该模块的广泛原因,如果不慎重/谨慎地使用,则会带来很多并发症。

答案 1 :(得分:0)

您要查找的错误消息位于响应正文中。可以使用response.text(或response.json()来访问它,因为特定的主体是JSON)。如果如您自己的答案所建议,如果您希望从raise_for_status()引发的异常中获取正文,则可以通过该异常的response属性:exception.response.text或{{1} }。