python - 请求 http 库 : include X-Request-ID

标签 python python-requests

我使用 requests Python 中的 HTTP 客户端库。

有时 HTTP 请求失败,我会收到状态为 500 的 HTTP 响应.

这可以在 CI 或生产中,我看到这样的东西:

AssertionError: 200 != 500 : <Response [500]>

这没什么帮助。

如果我能看到 X-Request-ID 就好了在上面的消息中。在我的环境中,每个 HTTP 响应都存在。

这意味着请求库的 HTTP 响应对象应该添加它。

我想要 repr()看起来像<Response [500] XejfkmxcPfhM3dqhY2HJgQAAAAM>

因为这不是我的代码,而是请求库的代码,所以我不确定如何实现它。

如何包含 X-Request-ID在请求响应对象的 repr() 中?

最佳答案

如果我能做到,我宁愿创建自己的“响应流”,而不是使用任何类型的 monkey patching .我已经检查了请求库的来源,我们很高兴去那里!我们可以使用 requests Event Hooks system 实现所需的功能.

有一个工作示例,我们可以对响应执行任何操作。唯一的变化是我们必须使用我们自己的 Session 对象实例来使用该功能。但!如果我们不想覆盖任何源代码,我们可以做一个 linemonkey-patch,为默认的 api 调用覆盖默认的 Session 类,它会像魅力一样在任何地方工作。

我的解决方案在这里

import requests


class ResponseVerbose(requests.Response):
    extra_header_repr = 'X-Request-Guid'

    def __repr__(self):
        return '<Response [{}] {}: {}>'.format(
            self.status_code,
            self.extra_header_repr,
            self.headers.get(self.extra_header_repr, 'None')
        )


class Session(requests.Session):
    def __init__(self):
        super().__init__()

        self.hooks['response'] = self.build_response

    @staticmethod
    def build_response(resp, *args, **kwargs):
        """
        Let's rebuild the source response into required verbose response object using all fields from the original

        FYI: requests.adapters.HTTPAdapter.build_response
        """
        response = ResponseVerbose()
        response.status_code = resp.status_code
        response.headers = resp.headers
        response.encoding = resp.encoding
        response.raw = resp.raw
        response.reason = response.raw.reason
        response.url = resp.url
        response.cookies = resp.cookies.copy()
        response.request = resp.request
        response.connection = resp.connection

        return response


def main():
    url = 'https://stackoverflow.com/'

    sess = Session()
    print('response using our own session object: {}'.format(sess.get(url)))

    import requests.api
    requests.api.sessions.Session = Session
    print('response using monkey patched global Session class: {}'.format(requests.get(url)))


if __name__ == '__main__':
    main()

输出

# python test123.py
response using our own session object: <Response [200] X-Request-Guid: 0c446bb5-7c96-495d-a831-061f5e3c2afe>
response using monkey patched global Session class: <Response [200] X-Request-Guid: 1db5aea7-8bc9-496a-addc-1231e8543a89>

一个更短的例子,它使用了 Response.__getstate__() 函数

更多信息 https://github.com/psf/requests/blob/master/requests/models.py#L654

As I see from the source code, you shouldn't do it for very large content responses since it fetches the whole resp.content to be able to convert the response state into a state dict. So use it only if you know that there are not gigabytes in responses :)

这个函数看起来简单多了。

import requests


class ResponseVerbose(requests.Response):
    extra_header_repr = 'X-Request-Guid'

    def __repr__(self):
        return '<Response [{}] {}: {}>'.format(
            self.status_code,
            self.extra_header_repr,
            self.headers.get(self.extra_header_repr, 'None')
        )


class Session(requests.Session):
    def __init__(self):
        super().__init__()

        self.hooks['response'] = self.build_response

    @staticmethod
    def build_response(resp, *args, **kwargs):
        """
        Let's rebuild the source response into required verbose response object using all fields from the original

        FYI: requests.adapters.HTTPAdapter.build_response
        """

        response = ResponseVerbose()
        for k, v in resp.__getstate__().items():
            setattr(response, k, v)

        return response


def main():
    url = 'https://stackoverflow.com/'

    sess = Session()
    print('response using our own session object: {}'.format(sess.get(url)))

    import requests.api
    requests.api.sessions.Session = Session
    print('response using monkey patched global Session class: {}'.format(requests.get(url)))


if __name__ == '__main__':
    main()

The solution prints StackOverflow's extra response header X-Request-Guid just for example. This extra header I did easily configurable just to show how it could be done in the right way.

关于python - 请求 http 库 : include X-Request-ID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59193447/

相关文章:

Python-请求关闭 http 连接

python - 如何抓取嵌入的链接和表格信息

python - Python 网页抓取时的编码问题

python - 无法使用 Requests lib 登录 Facebook

python - 使用请求包python时打开的文件太多

python - 嵌套字典理解 : Too many values to unpack

php - Python wordpress xmlrpc -32700 错误与 wordpress4.8

python - 与freebase库相关

python - 通过在__init__.py 中导入子包来跳过导入路径中的目录名

python - 导入错误:没有名为 'Crypto' 的模块