How to retain cookies for xmlrpc.client in Python 3?

后端 未结 2 503
名媛妹妹
名媛妹妹 2021-01-21 02:32

The default Python xmlrpc.client.Transport (can be used with xmlrpc.client.ServerProxy) does not retain cookies, which are sometimes needed for cookie

相关标签:
2条回答
  • 2021-01-21 02:49

    Existing answer from GermainZ works only for HTTP. After a lot of time fighting with it, there is HTTPS adaptation. Note the context option which is crucial.

    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)
    

    The reason for it is that ServerProxy doesn't respect context option related to transport, if transport is specified, so we need to use it directly in Transport constructor.

    Usage:

    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'})
    
    0 讨论(0)
  • 2021-01-21 03:09

    This is a simple Transport subclass that will retain all cookies:

    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)
    

    Usage:

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

    Since xmlrpc.client in Python 3 has better suited hooks for this, it's much simpler than an equivalent Python 2 version.

    0 讨论(0)
提交回复
热议问题