示例#1
0
def http_request(method,
                 url,
                 data,
                 headers=None,
                 use_proxy=False,
                 max_retry=DEFAULT_RETRIES,
                 retry_codes=RETRY_CODES,
                 retry_delay=SHORT_DELAY_IN_SECONDS):

    global SECURE_WARNING_EMITTED

    host, port, secure, rel_uri = _parse_url(url)

    # Use the HTTP(S) proxy
    proxy_host, proxy_port = (None, None)
    if use_proxy:
        proxy_host, proxy_port = _get_http_proxy(secure=secure)

        if proxy_host or proxy_port:
            logger.verbose("HTTP proxy: [{0}:{1}]", proxy_host, proxy_port)

    # If httplib module is not built with ssl support,
    # fallback to HTTP if allowed
    if secure and not hasattr(httpclient, "HTTPSConnection"):
        if not conf.get_allow_http():
            raise HttpError("HTTPS is unavailable and required")

        secure = False
        if not SECURE_WARNING_EMITTED:
            logger.warn("Python does not include SSL support")
            SECURE_WARNING_EMITTED = True

    # If httplib module doesn't support HTTPS tunnelling,
    # fallback to HTTP if allowed
    if secure and \
        proxy_host is not None and \
        proxy_port is not None \
        and not hasattr(httpclient.HTTPSConnection, "set_tunnel"):

        if not conf.get_allow_http():
            raise HttpError("HTTPS tunnelling is unavailable and required")

        secure = False
        if not SECURE_WARNING_EMITTED:
            logger.warn("Python does not support HTTPS tunnelling")
            SECURE_WARNING_EMITTED = True

    msg = ''
    attempt = 0
    delay = retry_delay

    while attempt < max_retry:
        if attempt > 0:
            logger.info("[HTTP Retry] Attempt {0} of {1}: {2}", attempt + 1,
                        max_retry, msg)
            time.sleep(delay)

        attempt += 1
        delay = retry_delay

        try:
            resp = _http_request(method,
                                 host,
                                 rel_uri,
                                 port=port,
                                 data=data,
                                 secure=secure,
                                 headers=headers,
                                 proxy_host=proxy_host,
                                 proxy_port=proxy_port)
            logger.verbose("[HTTP Response] Status Code {0}", resp.status)

            if request_failed(resp):
                if _is_retry_status(resp.status, retry_codes=retry_codes):
                    msg = '[HTTP Retry] HTTP {0} Status Code {1}'.format(
                        method, resp.status)
                    if _is_throttle_status(resp.status):
                        delay = LONG_DELAY_IN_SECONDS
                        logger.info("[HTTP Delay] Delay {0} seconds for " \
                                    "Status Code {1}".format(
                                        delay, resp.status))
                    continue

            if resp.status in RESOURCE_GONE_CODES:
                raise ResourceGoneError()

            return resp

        except httpclient.HTTPException as e:
            msg = '[HTTP Failed] HTTP {0} HttpException {1}'.format(method, e)
            if _is_retry_exception(e):
                continue
            break

        except IOError as e:
            msg = '[HTTP Failed] HTTP {0} IOError {1}'.format(method, e)
            continue

    raise HttpError(msg)
def http_request(method,
                 url,
                 data,
                 headers=None,
                 use_proxy=False,
                 max_retry=DEFAULT_RETRIES,
                 retry_codes=RETRY_CODES,
                 retry_delay=DELAY_IN_SECONDS):

    global SECURE_WARNING_EMITTED

    host, port, secure, rel_uri = _parse_url(url)

    # Use the HTTP(S) proxy
    proxy_host, proxy_port = (None, None)
    if use_proxy:
        proxy_host, proxy_port = _get_http_proxy(secure=secure)

        if proxy_host or proxy_port:
            logger.verbose("HTTP proxy: [{0}:{1}]", proxy_host, proxy_port)

    # If httplib module is not built with ssl support,
    # fallback to HTTP if allowed
    if secure and not hasattr(httpclient, "HTTPSConnection"):
        if not conf.get_allow_http():
            raise HttpError("HTTPS is unavailable and required")

        secure = False
        if not SECURE_WARNING_EMITTED:
            logger.warn("Python does not include SSL support")
            SECURE_WARNING_EMITTED = True

    # If httplib module doesn't support HTTPS tunnelling,
    # fallback to HTTP if allowed
    if secure and \
        proxy_host is not None and \
        proxy_port is not None \
        and not hasattr(httpclient.HTTPSConnection, "set_tunnel"):

        if not conf.get_allow_http():
            raise HttpError("HTTPS tunnelling is unavailable and required")

        secure = False
        if not SECURE_WARNING_EMITTED:
            logger.warn("Python does not support HTTPS tunnelling")
            SECURE_WARNING_EMITTED = True

    msg = ''
    attempt = 0
    delay = 0
    was_throttled = False

    while attempt < max_retry:
        if attempt > 0:
            # Compute the request delay
            # -- Use a fixed delay if the server ever rate-throttles the request
            #    (with a safe, minimum number of retry attempts)
            # -- Otherwise, compute a delay that is the product of the next
            #    item in the Fibonacci series and the initial delay value
            delay = THROTTLE_DELAY_IN_SECONDS \
                        if was_throttled \
                        else _compute_delay(retry_attempt=attempt,
                                            delay=retry_delay)

            logger.verbose(
                "[HTTP Retry] "
                "Attempt {0} of {1} will delay {2} seconds: {3}", attempt + 1,
                max_retry, delay, msg)

            time.sleep(delay)

        attempt += 1

        try:
            resp = _http_request(method,
                                 host,
                                 rel_uri,
                                 port=port,
                                 data=data,
                                 secure=secure,
                                 headers=headers,
                                 proxy_host=proxy_host,
                                 proxy_port=proxy_port)
            logger.verbose("[HTTP Response] Status Code {0}", resp.status)

            if request_failed(resp):
                if _is_retry_status(resp.status, retry_codes=retry_codes):
                    msg = '[HTTP Retry] {0} {1} -- Status Code {2}'.format(
                        method, url, resp.status)
                    # Note if throttled and ensure a safe, minimum number of
                    # retry attempts
                    if _is_throttle_status(resp.status):
                        was_throttled = True
                        max_retry = max(max_retry, THROTTLE_RETRIES)
                    continue

            if resp.status in RESOURCE_GONE_CODES:
                raise ResourceGoneError()

            # Map invalid container configuration errors to resource gone in
            # order to force a goal state refresh, which in turn updates the
            # container-id header passed to HostGAPlugin.
            # See #1294.
            if _is_invalid_container_configuration(resp):
                raise ResourceGoneError()

            return resp

        except httpclient.HTTPException as e:
            clean_url = redact_sas_tokens_in_urls(url)
            msg = '[HTTP Failed] {0} {1} -- HttpException {2}'.format(
                method, clean_url, e)
            if _is_retry_exception(e):
                continue
            break

        except IOError as e:
            IOErrorCounter.increment(host=host, port=port)
            clean_url = redact_sas_tokens_in_urls(url)
            msg = '[HTTP Failed] {0} {1} -- IOError {2}'.format(
                method, clean_url, e)
            continue

    raise HttpError("{0} -- {1} attempts made".format(msg, attempt))
示例#3
0
def http_request(method,
                 url,
                 data,
                 headers=None,
                 use_proxy=False,
                 max_retry=None,
                 retry_codes=None,
                 retry_delay=DELAY_IN_SECONDS,
                 redact_data=False):

    if max_retry is None:
        max_retry = DEFAULT_RETRIES
    if retry_codes is None:
        retry_codes = RETRY_CODES
    global SECURE_WARNING_EMITTED  # pylint: disable=W0603

    host, port, secure, rel_uri = _parse_url(url)

    # Use the HTTP(S) proxy
    proxy_host, proxy_port = (None, None)
    if use_proxy and not bypass_proxy(host):
        proxy_host, proxy_port = _get_http_proxy(secure=secure)

        if proxy_host or proxy_port:
            logger.verbose("HTTP proxy: [{0}:{1}]", proxy_host, proxy_port)

    # If httplib module is not built with ssl support,
    # fallback to HTTP if allowed
    if secure and not hasattr(httpclient, "HTTPSConnection"):
        if not conf.get_allow_http():
            raise HttpError("HTTPS is unavailable and required")

        secure = False
        if not SECURE_WARNING_EMITTED:
            logger.warn("Python does not include SSL support")
            SECURE_WARNING_EMITTED = True

    # If httplib module doesn't support HTTPS tunnelling,
    # fallback to HTTP if allowed
    if secure and \
        proxy_host is not None and \
        proxy_port is not None \
        and not hasattr(httpclient.HTTPSConnection, "set_tunnel"):

        if not conf.get_allow_http():
            raise HttpError("HTTPS tunnelling is unavailable and required")

        secure = False
        if not SECURE_WARNING_EMITTED:
            logger.warn("Python does not support HTTPS tunnelling")
            SECURE_WARNING_EMITTED = True

    msg = ''
    attempt = 0
    delay = 0
    was_throttled = False

    while attempt < max_retry:
        if attempt > 0:
            # Compute the request delay
            # -- Use a fixed delay if the server ever rate-throttles the request
            #    (with a safe, minimum number of retry attempts)
            # -- Otherwise, compute a delay that is the product of the next
            #    item in the Fibonacci series and the initial delay value
            delay = THROTTLE_DELAY_IN_SECONDS \
                        if was_throttled \
                        else _compute_delay(retry_attempt=attempt,
                                            delay=retry_delay)

            logger.verbose(
                "[HTTP Retry] "
                "Attempt {0} of {1} will delay {2} seconds: {3}", attempt + 1,
                max_retry, delay, msg)

            time.sleep(delay)

        attempt += 1

        try:
            resp = _http_request(method,
                                 host,
                                 rel_uri,
                                 port=port,
                                 data=data,
                                 secure=secure,
                                 headers=headers,
                                 proxy_host=proxy_host,
                                 proxy_port=proxy_port,
                                 redact_data=redact_data)
            logger.verbose("[HTTP Response] Status Code {0}", resp.status)

            if request_failed(resp):
                if _is_retry_status(resp.status, retry_codes=retry_codes):
                    msg = '[HTTP Retry] {0} {1} -- Status Code {2}'.format(
                        method, url, resp.status)
                    # Note if throttled and ensure a safe, minimum number of
                    # retry attempts
                    if _is_throttle_status(resp.status):
                        was_throttled = True
                        max_retry = max(max_retry, THROTTLE_RETRIES)
                    continue

            # If we got a 410 (resource gone) for any reason, raise an exception. The caller will handle it by
            # forcing a goal state refresh and retrying the call.
            if resp.status in RESOURCE_GONE_CODES:
                response_error = read_response_error(resp)
                raise ResourceGoneError(response_error)

            # If we got a 400 (bad request) because the container id is invalid, it could indicate a stale goal
            # state. The caller will handle this exception by forcing a goal state refresh and retrying the call.
            if resp.status == httpclient.BAD_REQUEST:
                response_error = read_response_error(resp)
                if INVALID_CONTAINER_CONFIGURATION in response_error:
                    raise InvalidContainerError(response_error)

            return resp

        except httpclient.HTTPException as e:
            clean_url = _trim_url_parameters(url)
            msg = '[HTTP Failed] {0} {1} -- HttpException {2}'.format(
                method, clean_url, e)
            if _is_retry_exception(e):
                continue
            break

        except IOError as e:
            IOErrorCounter.increment(host=host, port=port)
            clean_url = _trim_url_parameters(url)
            msg = '[HTTP Failed] {0} {1} -- IOError {2}'.format(
                method, clean_url, e)
            continue

    raise HttpError("{0} -- {1} attempts made".format(msg, attempt))
示例#4
0
def http_request(method,
                url, data, headers=None,
                use_proxy=False,
                max_retry=DEFAULT_RETRIES,
                retry_codes=RETRY_CODES,
                retry_delay=DELAY_IN_SECONDS):

    global SECURE_WARNING_EMITTED

    host, port, secure, rel_uri = _parse_url(url)

    # Use the HTTP(S) proxy
    proxy_host, proxy_port = (None, None)
    if use_proxy and not bypass_proxy(host):
        proxy_host, proxy_port = _get_http_proxy(secure=secure)

        if proxy_host or proxy_port:
            logger.verbose("HTTP proxy: [{0}:{1}]", proxy_host, proxy_port)

    # If httplib module is not built with ssl support,
    # fallback to HTTP if allowed
    if secure and not hasattr(httpclient, "HTTPSConnection"):
        if not conf.get_allow_http():
            raise HttpError("HTTPS is unavailable and required")

        secure = False
        if not SECURE_WARNING_EMITTED:
            logger.warn("Python does not include SSL support")
            SECURE_WARNING_EMITTED = True

    # If httplib module doesn't support HTTPS tunnelling,
    # fallback to HTTP if allowed
    if secure and \
        proxy_host is not None and \
        proxy_port is not None \
        and not hasattr(httpclient.HTTPSConnection, "set_tunnel"):

        if not conf.get_allow_http():
            raise HttpError("HTTPS tunnelling is unavailable and required")

        secure = False
        if not SECURE_WARNING_EMITTED:
            logger.warn("Python does not support HTTPS tunnelling")
            SECURE_WARNING_EMITTED = True

    msg = ''
    attempt = 0
    delay = 0
    was_throttled = False

    while attempt < max_retry:
        if attempt > 0:
            # Compute the request delay
            # -- Use a fixed delay if the server ever rate-throttles the request
            #    (with a safe, minimum number of retry attempts)
            # -- Otherwise, compute a delay that is the product of the next
            #    item in the Fibonacci series and the initial delay value
            delay = THROTTLE_DELAY_IN_SECONDS \
                        if was_throttled \
                        else _compute_delay(retry_attempt=attempt,
                                            delay=retry_delay)

            logger.verbose("[HTTP Retry] "
                        "Attempt {0} of {1} will delay {2} seconds: {3}",
                        attempt+1,
                        max_retry,
                        delay,
                        msg)

            time.sleep(delay)

        attempt += 1

        try:
            resp = _http_request(method,
                                 host,
                                 rel_uri,
                                 port=port,
                                 data=data,
                                 secure=secure,
                                 headers=headers,
                                 proxy_host=proxy_host,
                                 proxy_port=proxy_port)
            logger.verbose("[HTTP Response] Status Code {0}", resp.status)

            if request_failed(resp):
                if _is_retry_status(resp.status, retry_codes=retry_codes):
                    msg = '[HTTP Retry] {0} {1} -- Status Code {2}'.format(method, url, resp.status)
                    # Note if throttled and ensure a safe, minimum number of
                    # retry attempts
                    if _is_throttle_status(resp.status):
                        was_throttled = True
                        max_retry = max(max_retry, THROTTLE_RETRIES)
                    continue

            if resp.status in RESOURCE_GONE_CODES:
                raise ResourceGoneError()

            # Map invalid container configuration errors to resource gone in
            # order to force a goal state refresh, which in turn updates the
            # container-id header passed to HostGAPlugin.
            # See #1294.
            if _is_invalid_container_configuration(resp):
                raise ResourceGoneError()

            return resp

        except httpclient.HTTPException as e:
            clean_url = redact_sas_tokens_in_urls(url)
            msg = '[HTTP Failed] {0} {1} -- HttpException {2}'.format(method, clean_url, e)
            if _is_retry_exception(e):
                continue
            break

        except IOError as e:
            IOErrorCounter.increment(host=host, port=port)
            clean_url = redact_sas_tokens_in_urls(url)
            msg = '[HTTP Failed] {0} {1} -- IOError {2}'.format(method, clean_url, e)
            continue

    raise HttpError("{0} -- {1} attempts made".format(msg, attempt))