【问题标题】:How to retain cookies for xmlrpc.client in Python 3?如何在 Python 3 中为 xmlrpc.client 保留 cookie?
【发布时间】:2017-11-15 01:22:45
【问题描述】:

默认的 Python xmlrpc.client.Transport(可与 xmlrpc.client.ServerProxy 一起使用)不保留 cookie,基于 cookie 的登录有时需要这些。

例如,以下代理在与 TapaTalk API(login method 使用 cookie 进行身份验证)一起使用时,在尝试修改帖子时会出现权限错误。

proxy = xmlrpc.client.ServerProxy(URL, xmlrpc.client.Transport())

网上有 Python 2 的 some solutions,但它们与 Python 3 不兼容。

如何使用保留 cookie 的Transport

【问题讨论】:

    标签: python cookies python-3.x xmlrpclib


    【解决方案1】:

    GermainZ 的现有答案仅适用于 HTTP。在与它斗争了很多时间之后,就有了 HTTPS 的适配。请注意context 选项,这是至关重要的。

    class CookiesTransport(xmlrpc.client.SafeTransport):
        """A SafeTransport (HTTPS) subclass that retains cookies over its lifetime."""
    
        # Note context option - it's required for success
        def __init__(self, context=None):
            super().__init__(context=context)
            self._cookies = []
    
        def send_headers(self, connection, headers):
            if self._cookies:
                connection.putheader("Cookie", "; ".join(self._cookies))
            super().send_headers(connection, headers)
    
        def parse_response(self, response):
            # This check is required if in some responses we receive no cookies at all
            if response.msg.get_all("Set-Cookie"):
                for header in response.msg.get_all("Set-Cookie"):
                    cookie = header.split(";", 1)[0]
                    self._cookies.append(cookie)
            return super().parse_response(response)
    

    原因是ServerProxy不尊重context与transport相关的选项,如果指定了transport,需要在Transport构造函数中直接使用。

    用法:

    import xmlrpc.client
    import ssl
    
    
    transport = CookiesTransport(context=ssl._create_unverified_context())
    # Note the closing slash in address as well, very important
    server = xmlrpc.client.ServerProxy("https://<api_link>/", transport=transport)
    
    # do stuff with server
    server.myApiFunc({'param1': 'x', 'param2': 'y'})
    

    【讨论】:

      【解决方案2】:

      这是一个简单的Transport 子类,它将保留所有 cookie:

      class CookiesTransport(xmlrpc.client.Transport):
      """A Transport subclass that retains cookies over its lifetime."""
      
          def __init__(self):
              super().__init__()
              self._cookies = []
      
          def send_headers(self, connection, headers):
              if self._cookies:
                  connection.putheader("Cookie", "; ".join(self._cookies))
              super().send_headers(connection, headers)
      
          def parse_response(self, response):
              for header in response.msg.get_all("Set-Cookie"):
                  cookie = header.split(";", 1)[0]
                  self._cookies.append(cookie)
              return super().parse_response(response)
      

      用法:

      proxy = xmlrpc.client.ServerProxy(URL, CookiesTransport())
      

      由于 Python 3 中的 xmlrpc.client 对此有更合适的钩子,因此它比等效的 Python 2 版本简单得多。

      【讨论】:

      • 请注意,这个 sn-p 不能按原样工作。因为如果服务器没有为某些请求发送 cookie(例如 - 只有在第一次“登录”调用之后才响应 cookie,而其他响应不包含它们),它将失败尝试 get_all("Set-Cookie")。所以这里需要额外检查
      猜你喜欢
      • 2015-07-14
      • 2012-07-15
      • 2022-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-03
      相关资源
      最近更新 更多