Перезагрузка образа WebKit на Post / Redirect / Get - PullRequest
0 голосов
/ 29 ноября 2010

Мы только что перепроектировали веб-приложение и в результате заметили ошибку в Chrome (но она предположительно влияет на все браузеры WebKit), которая вызывает полную перезагрузку изображения / js / css после Post / Redirect / Get. Наше приложение построено с использованием ASP.NET и использует множество Response.Redirect, что означает, что пользователи часто сталкиваются с этой проблемой. Есть сообщение об ошибке для проблемы с тестовым набором: https://bugs.webkit.org/show_bug.cgi?id=38690

Мы попытались решить эту проблему следующим образом:

  • Изменить все Response.Redirects, чтобы быть перенаправлениями JavaScript. Это было не идеально, потому что вместо перезагрузки изображений во время переходов страниц будет «белая вспышка».
  • Мы написали наш собственный обработчик HTTP для изображений, файлов CSS и JS. Мы установили его так, чтобы обработчик отправлял максимум 1 час. Когда клиент снова запрашивает файл, обработчик проверяет заголовок If-Modified-Since, отправленный браузером, чтобы узнать, обновлялся ли файл с момента его последней загрузки. Если даты совпадают, обработчик возвращает HTTP 302 (не изменен) с 0 для длины содержимого. Мы запустили тест, в котором при первой загрузке образа (HTTP 200) задержка составляла 10 секунд. Таким образом, в первый раз страница загружалась очень медленно. Если обработчик возвратил 302 (не изменено), задержки не было. Мы заметили, что Chrome будет по-прежнему «перезагружать» изображения, даже когда сервер вернул 302 (не изменено). Он не извлекает файл с сервера (в противном случае это приведет к задержке в 10 секунд), но все же мигает / перезагружает изображения. Таким образом, похоже, что Chrome игнорирует 302 и продолжает перезагружать изображения из своего кэша, вызывая «перезагрузку».

Мы проверили большие сайты, чтобы убедиться, что они как-то это исправили, но такие сайты, как NewEgg и Amazon, также затронуты.

Кто-нибудь нашел решение этой проблемы? Или способ минимизировать эффект?

Спасибо.

Ответы [ 2 ]

1 голос
/ 04 февраля 2011

Это ошибка. Единственный «обходной путь», который я видел до сих пор, - это использовать заголовок Refresh вместо заголовка Location для перенаправления. Это далеко от идеала.

Ошибка 38690 - Отправка сообщения POST, которое приводит к перенаправлению сервера, приводит к повторной загрузке всех кэшированных элементов

Кроме того, этот вопрос является дубликатом " Полная перезагрузка страницы в Post / Redirect / Get игнорируя элемент управления кэшем ".

0 голосов
/ 07 апреля 2011

Я сам столкнулся с этой проблемой на сайте веб-форм ASP.NET, который использует Response.Redirect (url, false) после сообщения на многих из его страниц.

Из прочтения спецификации HTTP / 1.1 кажется, что код ответа 303 будет правильным для реализации поведения Request: POST, Response: Redirect. К сожалению, изменение кода состояния не позволяет кешированию браузера работать в Chrome.

Я реализовал обходной путь, описанный в посте выше, создав специальный модуль для нестатического контента. Я также удаляю содержимое ответа из 302-х, чтобы избежать появления моргания «объект перемещен сюда». Это, вероятно, относится только к заголовкам обновления. Комментарии приветствуются!

public class WebKitHTTPHeaderFixModule : IHttpModule 
{ 
    public void Init(HttpApplication httpApp) 
    { 
        // Attach application event handlers. 
        httpApp.PreSendRequestHeaders += new EventHandler(httpApp_PreSendRequestHeaders);
    }

    void httpApp_PreSendRequestHeaders(object sender, EventArgs e)
    {
        HttpContext context = HttpContext.Current;

        if (context.Response.StatusCode == 302)
        {
            context.Response.ClearContent();

            // If Request is POST and Response is 302 and browser is Webkit use a refresh header
            if (context.Request.HttpMethod.Equals("POST", StringComparison.OrdinalIgnoreCase) && context.Request.Headers["User-Agent"].ToLower().Contains("webkit"))
            {
                string location = context.Response.Headers["Location"];
                context.Response.StatusCode = 200;
                context.Response.AppendHeader("Refresh", "0; url=" + location);
            }
        }
    }

    public void Dispose() 
    {} 
}

Примечание: я не думаю, что это будет работать с не перегруженной версией Response.Redirect, поскольку она вызывает Response.End ().

...