def build_opener(*handlers, **kw):
    """Create an opener object from a list of handlers.

    The opener will use several default handlers, including support
    for HTTP and FTP.

    If any of the handlers passed as arguments are subclasses of the
    default handlers, the default handlers will not be used.
    """
    import types

    def isclass(obj):
        return isinstance(obj, types.ClassType) or hasattr(obj, "__bases__")

    opener = OpenerDirector()
    default_classes = [
        ProxyHandler, UnknownHandler, HTTPHandler, HTTPDefaultErrorHandler,
        HTTPRedirectHandler, FTPHandler, FileHandler, HTTPErrorProcessor
    ]
    check_classes = list(default_classes)
    check_classes.append(HTTPSContextHandler)
    skip = []
    for klass in check_classes:
        for check in handlers:
            if isclass(check):
                if issubclass(check, klass):
                    skip.append(klass)
            elif isinstance(check, klass):
                skip.append(klass)

    for klass in default_classes:
        if klass not in skip:
            opener.add_handler(klass())

    # Pick up SSL context from keyword settings
    ssl_context = kw.get('ssl_context')

    # Add the HTTPS handler with ssl_context
    if HTTPSContextHandler not in skip:
        opener.add_handler(HTTPSContextHandler(ssl_context))

    for h in handlers:
        if isclass(h):
            h = h()
        opener.add_handler(h)

    return opener
Exemple #2
0
def open_url(url, config, data=None, handlers=None):
    """Attempts to open a connection to a specified URL.
    @param url: URL to attempt to open
    @param config: SSL context configuration
    @type config: Configuration
    @param data: HTTP POST data
    @type data: str
    @param handlers: list of custom urllib2 handlers to add to the request
    @type handlers: iterable
    @return: tuple (
        returned HTTP status code or 0 if an error occurred
        returned message or error description
        response object)
    """
    debuglevel = 1 if config.debug else 0

    # Set up handlers for URL opener.
    if config.cookie:
        cj = config.cookie
    else:
        cj = cookiejar_.CookieJar()

    # Use a cookie processor that accumulates cookies when redirects occur so
    # that an application can redirect for authentication and retain both any
    # cookies for the application and the security system (c.f.,
    # urllib2.HTTPCookieProcessor which replaces cookies).
    cookie_handler = AccumulatingHTTPCookieProcessor(cj)

    if not handlers:
        handlers = []

    handlers.append(cookie_handler)

    if config.debug:
        http_handler = HTTPHandler_(debuglevel=debuglevel)
        https_handler = HTTPSContextHandler(config.ssl_context,
                                            debuglevel=debuglevel)
        handlers.extend([http_handler, https_handler])

    if config.http_basicauth:
        # currently only supports http basic auth
        auth_handler = HTTPBasicAuthHandler_(HTTPPasswordMgrWithDefaultRealm_())
        auth_handler.add_password(realm=None, uri=url,
                                  user=config.httpauth[0],
                                  passwd=config.httpauth[1])
        handlers.append(auth_handler)


    # Explicitly remove proxy handling if the host is one listed in the value of
    # the no_proxy environment variable because urllib2 does use proxy settings
    # set via http_proxy and https_proxy, but does not take the no_proxy value
    # into account.
    if not _should_use_proxy(url, config.no_proxy):
        handlers.append(ProxyHandler_({}))
        log.debug("Not using proxy")
    elif config.proxies:
        handlers.append(ProxyHandler_(config.proxies))
        log.debug("Configuring proxies: %s" % config.proxies)

    opener = build_opener(*handlers, ssl_context=config.ssl_context)

    headers = config.headers
    if headers is None:
        headers = {}

    request = Request_(url, data, headers)

    # Open the URL and check the response.
    return_code = 0
    return_message = ''
    response = None

    # FIXME
    response = opener.open(request)

    try:
        response = opener.open(request)
        return_message = response.msg
        return_code = response.code
        if log.isEnabledFor(logging.DEBUG):
            for index, cookie in enumerate(cj):
                log.debug("%s  :  %s", index, cookie)

    except HTTPError_ as exc:
        return_code = exc.code
        return_message = "Error: %s" % exc.msg
        if log.isEnabledFor(logging.DEBUG):
            log.debug("%s %s", exc.code, exc.msg)

    except Exception as exc:
        return_message = "Error: %s" % exc.__str__()
        if log.isEnabledFor(logging.DEBUG):
            import traceback
            log.debug(traceback.format_exc())

    return (return_code, return_message, response)