Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Browser returning HTTP 200 with an empty responseText

Tags:

jquery

ajax

I use the following code to retry operations that return HTTP 502, 503 or 504:

/**
 * @function RetryDelayFunction
 * Returns the amount of time to wait after a failure.
 *
 * @param {Number} retries the number of times the operation has been retried
 * @return {Number} the number of milliseconds to wait before retrying the operation
 */

/**
 * @typedef {Object} RetryAjaxOptions
 *
 * @property {Number} retries the number of times to retry a failed operation
 * @param {RetryDelayFunction} delayFunction maps a failure count to a delay in milliseconds
 * @param {Array} errorCodes the HTTP response codes that should trigger a retry
 */

/**
 * Retries HTTP requests using an exponential back-off in case of HTTP 502, 503, 504. Based on
 * https://github.com/execjosh/jquery-ajax-retry and http://javadoc.google-http-java-client.googlecode.com/hg/1.15.0-rc/com/google/api/client/util/ExponentialBackOff.html
 *
 * The $.ajax() settings object must contain a {@code retry} key to enable this functionality.
 * This object is of type {@link RetryAjaxOptions} and may be used to override the default behavior.
 */
function installAjaxRetries()
{
    "use strict";
    /**
     * Do nothing.
     */
    var noOpFunction = function()
    {
    };

    var delayInitialIntervalMs = 250;
    var delayIntervalMultiplier = 1.5;
    var delayRandomizationFactor = 0.5;

    /**
     * @function RetryDelayFunction
     */
    var defaultDelayFunction = function(retries)
    {
        var retryInterval = delayInitialIntervalMs * Math.pow(delayIntervalMultiplier, retries);
        var delta = retryInterval * delayRandomizationFactor;
        var min = retryInterval - delta;
        var max = retryInterval + delta;
        return (Math.random() * (max - min + 1)) + min;
    };

    var MIN_RETRIES = 1;
    var DEFAULT_RETRIES = 3;
    var DEFAULT_ERROR_CODES = [502, 503, 504];

    var DEFAULT_OPTIONS =
        {
            retries: DEFAULT_RETRIES,
            delayFunction: defaultDelayFunction,
            errorCodes: DEFAULT_ERROR_CODES
        };
    var originalAjaxFunction = $.ajax;
    var ajaxWithRetry = function(settings)
    {
        settings = $.extend(true, {}, $.ajaxSettings, settings);
        if (!settings.retry)
            return originalAjaxFunction(settings);

        var retries = 0;
        var options = $.extend(true, {}, $.ajaxRetrySettings, settings.retry);
        var originalErrorFunction = settings.error || noOpFunction;
        var originalCompleteFunction = settings.complete || noOpFunction;

        // Clamp options
        options.retries = Math.max(MIN_RETRIES, options.retries);
        options.delayFunction = options.delayFunction || defaultDelayFunction;

        // Override error function
        settings.error = function(xhr, textStatus, errorThrown)
        {
            if ($.inArray(xhr.status, options.errorCodes) < 0 || retries >= options.retries)
            {
                // Give up and call the original error() function
                originalErrorFunction.call(this, xhr, textStatus, errorThrown);
                return;
            }
            // The complete() handler will retry the operation
        };

        // Override complete function
        settings.complete = function(xhr, textStatus)
        {
            if ($.inArray(xhr.status, options.errorCodes) < 0 || retries >= options.retries)
            {
                // Give up and call the original complete() function
                originalCompleteFunction.call(this, xhr, textStatus);
                return;
            }
            var delayMs = options.delayFunction(retries);
            ++retries;
            window.setTimeout(function()
            {
                originalAjaxFunction(settings);
            }, delayMs);
        };

        originalAjaxFunction(settings);
        return settings.xhr;
    };

    var ajaxRetrySetup = function(options)
    {
        DEFAULT_OPTIONS = $.extend(true, DEFAULT_OPTIONS, options);
        $.ajaxRetrySettings = DEFAULT_OPTIONS;
        return DEFAULT_OPTIONS;
    };

    $.ajaxRetrySettings = DEFAULT_OPTIONS;
    $.ajaxRetrySetup = ajaxRetrySetup;
    $.ajax = ajaxWithRetry;
}
installAjaxRetries();

Ever since I started using this code, some AJAX calls began returning HTTP 200 with an empty responseText. What's weird is that first request is failing (no retrying is actually taking place) and simply commenting out the code that overrides settings.complete fixes the problem. I am using Chrome 29.0.1547.57 m.

Why does overriding settings.complete cause this problem?

UPDATE: I control the server, so I know for a fact it never returns HTTP 200 with an empty response.

UPDATE2: I can no longer reproduce the problem and I don't recall what I did to fix it. If I can't reproduce it in the next couple of months I plan on closing it.

like image 203
Gili Avatar asked Nov 12 '22 23:11

Gili


1 Answers

may be you are trying cross domain server.set response header to allow-access-origin

like image 159
Shekhar Avatar answered Nov 15 '22 12:11

Shekhar