NodeJS / express: kod stanu pamięci podręcznej i 304

92

Kiedy przeładowuję witrynę utworzoną za pomocą express, otrzymuję pustą stronę w Safari (nie w Chrome), ponieważ serwer NodeJS wysyła mi kod stanu 304.

Jak to rozwiązać?

Oczywiście może to być tylko problem Safari, ale w rzeczywistości działa dobrze na wszystkich innych stronach internetowych, więc musi to być również problem na moim serwerze NodeJS.

Do generowania stron używam Jade z res.render.

Aktualizacja: Wygląda na to, że ten problem występuje, ponieważ Safari wysyła 'cache-control': 'max-age=0'przy ponownym załadowaniu.

Aktualizacja 2: mam teraz obejście, ale czy istnieje lepsze rozwiązanie? Obejście:

app.get('/:language(' + content.languageSelector + ')/:page', function (req, res)
{
    // Disable caching for content files
    res.header("Cache-Control", "no-cache, no-store, must-revalidate");
    res.header("Pragma", "no-cache");
    res.header("Expires", 0);

    // rendering stuff here…
}

Aktualizacja 3: Tak więc cała część kodu to obecnie:

app.get('/:language(' + content.languageSelector + ')/:page', pageHandle);

function pageHandle (req, res)
{
    var language = req.params.language;
    var thisPage = content.getPage(req.params.page, language);

    if (thisPage)
    {
        // Disable caching for content files
        res.header("Cache-Control", "no-cache, no-store, must-revalidate");
        res.header("Pragma", "no-cache");
        res.header("Expires", 0);

        res.render(thisPage.file + '_' + language, {
            thisPage : thisPage,
            language: language,
            languages: content.languages,
            navigation: content.navigation,
            footerNavigation: content.footerNavigation,
            currentYear: new Date().getFullYear()
        });
    }
    else
    {
        error404Handling(req, res);
    }
}
h345k34cr
źródło
1
304 nie jest problemem. Oznacza to po prostu, że twoja odpowiedź nie jest modyfikowana, a przeglądarka przechodzi do pamięci podręcznej, aby pobrać zasób. Czy możesz wysłać odpowiedni kod, w którym występuje anomalia.
Akshat Jiwan Sharma
3
tak, w rzeczywistości nie jest zmodyfikowany, ale Safari opróżnia pamięć podręczną na CMD + R (przeładuj), a serwer mówi tylko, że się nie zmienił.
h345k34cr
W jaki sposób pusta strona jest powiązana z kodem statusu 304? Węzeł wysyła również 304 do innych przeglądarek.
user568109,
2
Jest to związane, ponieważ w przypadku 304
treść
1
@AkshatJiwanSharma Każdy program jest opracowywany tak, aby dokładnie spełniać warunki umowy właściciela produktu. Właściciel produktu to ten, który jest właścicielem kodu i płaci pieniądze, a nie jakaś organizacja, która pisze dokumenty, które nikogo nie obchodzą. Jeśli w umowie jest napisane „200”, to absolutnie każdy stan, który nie jest równy „200”, jest błędem. Kiedy pojawia się błąd, MUSZĘ przepisać kod, aż wszystko będzie dokładnie takie, jak oczekiwano. W3C nie ma nic do powiedzenia w tej sprawie.
Gherman

Odpowiedzi:

107

Najłatwiejsze rozwiązanie:

app.disable('etag');

Alternatywne rozwiązanie tutaj, jeśli chcesz mieć większą kontrolę:

http://vlasenko.org/2011/10/12/expressconnect-static-set-last-modified-to-now-to-avoid-304-not-modified/

zmieszane
źródło
2
Czy mógłbyś wyjaśnić „najłatwiejsze rozwiązanie” lub wskazać, jak to wpływa?
Samuel Méndez
1
@ SamuelMéndez zasadniczo wyłącza buforowanie, wiki na etag ma wiele dobrych informacji en.wikipedia.org/wiki/HTTP_ETag
blented
Pracował dla mnie :)
Naveen Kumar V
3

Jak powiedziałeś, Safari wysyła Cache-Control: max-age=0przy ponownym załadowaniu. Express (a dokładniej zależność Express, node-fresh) traktuje pamięć podręczną jako nieaktualną po Cache-Control: no-cacheodebraniu nagłówków, ale nie robi tego samego dla Cache-Control: max-age=0. Z tego, co wiem, prawdopodobnie powinno. Ale nie jestem ekspertem w buforowaniu.

Poprawka polega na zmianie (obecnie) linii 37 node-fresh/index.jsz

if (cc && cc.indexOf('no-cache') !== -1) return false;  

do

if (cc && (cc.indexOf('no-cache') !== -1 ||
  cc.indexOf('max-age=0') !== -1)) return false;

Rozwidliłem node-fresh i express, aby uwzględnić tę poprawkę w moim projekcie package.jsonprzez npm, możesz zrobić to samo. Oto moje widelce, na przykład:

https://github.com/stratusdata/node-fresh https://github.com/stratusdata/express#safari-reload-fix

Gałąź safari-reload-fix jest oparta na tagu 3.4.7.

James P. Javery
źródło
Świetna robota! Widzę, że express 3.5.1 zawiera twoją poprawkę przez node-fresh 0.2.2.
Clafou
Właściwie to się mylę, Twoja poprawka została cofnięta i nie dotarła do wersji 0.2.2. Nadal nie ma świeżej / ekspresowej poprawki.
Clafou
2

Miałem ten sam problem w Safari i Chrome (jedyne, które testowałem), ale właśnie zrobiłem coś, co wydaje się działać, przynajmniej nie byłem w stanie odtworzyć problemu, odkąd dodałem rozwiązanie. To, co zrobiłem, to dodanie metatagu do nagłówka z wygenerowanym znacznikiem czasu. Nie wydaje się właściwe, ale jest proste :)

<meta name="304workaround" content="2013-10-24 21:17:23">

Zaktualizuj PS O ile wiem, problem znika, gdy usuwam serwer proxy mojego węzła (przez proxy rozumiem zarówno moduł express.vhost, jak i http-proxy), co jest dziwne ...

user907567
źródło
Używam również serwera proxy Apache, może to być problem. Moje obejście polegało na wyłączeniu buforowania dla witryn z treścią z nagłówkami http.
h345k34cr
Wyłączenie pamięci podręcznej przez nagłówki jest zdecydowanie najlepszym rozwiązaniem. Na początku nie działało to dla mnie, ale teraz działa. Innymi słowy, musiałem gdzieś
popełnić
1

Spróbuj skorzystać z przeglądania prywatnego w Safari lub usunąć całą pamięć podręczną / pliki cookie.

Miałem podobne problemy podczas korzystania z Chrome, gdy przeglądarka myślała, że ​​ma witrynę w pamięci podręcznej, ale w rzeczywistości nie miała.

Część żądania http, która powoduje, że serwer odpowiada na 304, to etag. Wygląda na to, że Safari wysyła właściwy etag bez odpowiedniej pamięci podręcznej.

sbugert
źródło
to działa u mnie, gdy próbowałem usunąć całą pamięć podręczną, dzięki
Yuttanant Suwansiri
0

Wiem, stare pytanie. Wyłączenie funkcji pamięci podręcznej nie jest potrzebne i nie jest najlepszym sposobem na rozwiązanie problemu. Wyłączając funkcję pamięci podręcznej, serwer musi pracować ciężej i generuje większy ruch. Również przeglądarka i urządzenie muszą pracować ciężej, szczególnie na urządzeniach mobilnych może to być problem.

Pustą stronę można łatwo rozwiązać za pomocą klawisza Shift + przycisk odświeżania w przeglądarce.

Pusta strona może być wynikiem:

  • błąd w kodzie
  • podczas testowania podałeś pustą stronę (nie pamiętasz), która jest buforowana przez przeglądarkę
  • błąd w Safari (jeśli tak, zgłoś go do Apple i nie próbuj samodzielnie go naprawiać)

Wypróbuj najpierw klawisz Shift + przycisk ponownego ładowania i sprawdź, czy problem nadal występuje, i przejrzyj kod.

Codebeat
źródło