Ticket #4922: cookieagent_composed2.patch

File cookieagent_composed2.patch, 4.1 KB (added by gabrtv, 5 years ago)

composed, minus dependency on persistent connections

  • twisted/web/client.py

     
    11# -*- test-case-name: twisted.web.test.test_webclient -*-
    22# Copyright (c) 2001-2010 Twisted Matrix Laboratories.
    33# See LICENSE for details.
     4import urllib2
    45
    56"""
    67HTTP client.
     
    848849                p.transport.loseConnection()
    849850        self._protocolCache = {}
    850851
     852class CookieAgent(object):
     853    """
     854    L{CookieAgent} extends the basic L{Agent} to add RFC-compliant
     855    handling of HTTP cookies.  Cookies are written to and extracted
     856    from a C{cookielib.CookieJar} instance.
     857    """
     858    def __init__(self, agent, cookieJar, *args, **kwargs):
     859        self._agent = agent
     860        self.jar = cookieJar
    851861
     862    def request(self, method, uri, headers=None, bodyProducer=None):
     863        """
     864        Issue a new request.
     865
     866        @param method: The request method to send.
     867        @type method: C{str}
     868
     869        @param uri: The request URI send.
     870        @type uri: C{str}
     871
     872        @param headers: The request headers to send.  If no I{Host} header is
     873            included, one will be added based on the request URI.
     874        @type headers: L{Headers}
     875
     876        @param bodyProducer: An object which will produce the request body or,
     877            if the request body is to be empty, L{None}.
     878        @type bodyProducer: L{IBodyProducer} provider
     879
     880        @return: A L{Deferred} which fires with the result of the request (a
     881            L{Response} instance), or fails if there is a problem setting up a
     882            connection over which to issue the request.  It may also fail with
     883            L{SchemeNotSupported} if the scheme of the given URI is not
     884            supported.
     885        @rtype: L{Deferred}
     886        """
     887        # setting cookie header explicitly will disable automatic request cookies
     888        if not headers.hasHeader('cookie'):
     889            last_req = self._urllib2Request(uri)
     890            self.jar.add_cookie_header(last_req)
     891            cookie_header = last_req.get_header('Cookie', None)
     892            if cookie_header is not None:
     893                headers.addRawHeader('cookie', cookie_header)       
     894        d = self._agent.request(method, uri, headers, bodyProducer)
     895        d.addCallback(self._extractCookies, last_req)
     896        return d
     897   
     898    def _urllib2Request(self, uri):
     899        """
     900        Given a URI, return a urllib2.Request instance for use with cookielib
     901       
     902        @param uri: The request URI send.
     903        @type uri: C{str}
     904
     905        @return: A C{urllib2.Request} instance for use with cookielib
     906        @rtype: C{urllib2.Request}
     907        """
     908        return urllib2.Request(uri)
     909
     910    def _extractCookies(self, response, request):
     911        """
     912        Extract response cookies and store them in the cookie jar
     913
     914        @param response: A urllib2-style response object
     915        @type uri: C{urllib.Response}
     916
     917        @param response: A urllib2-style response object
     918        @type uri: C{urllib.Response}
     919
     920        @return: A L{Deferred} which fires with the result of the request (a
     921            L{Response} instance), or fails if there is a problem setting up a
     922            connection over which to issue the request.  It may also fail with
     923            L{SchemeNotSupported} if the scheme of the given URI is not
     924            supported.
     925        @rtype: L{Deferred}
     926        """
     927        # construct a urllib2-style response object
     928        class _Response(object):
     929            def info(self):
     930                class _Meta(object):
     931                    def getheaders(self, name):
     932                        return response.headers.getRawHeaders(name.lower(), [])
     933                return _Meta()
     934        resp = _Response()
     935        self.jar.extract_cookies(resp, request)
     936        return response
     937
    852938__all__ = [
    853939    'PartialDownloadError',
    854940    'HTTPPageGetter', 'HTTPPageDownloader', 'HTTPClientFactory', 'HTTPDownloader',
    855941    'getPage', 'downloadPage',
    856942
    857     'ResponseDone', 'Response', 'Agent']
     943    'ResponseDone', 'Response', 'Agent', 'CookieAgent']