Bagaimana cara menambahkan header no-cache ke semua 404 halaman yang dilayani oleh apache dan nginx?

9

Saya baru-baru ini mengalami masalah setelah beralih ke Cloudflare, dan solusinya adalah menghentikan Cloudflare dari caching 404 tanggapan.

Dalam pengaturan multi-server kami yang seimbang, kadang-kadang 404 terjadi, tetapi cepat diperbaiki oleh rsync (via lsyncd). Sebelum Cloudflare, permintaan ulang ke file 404 akan dengan cepat menjadi 200 karena rsync melakukan tugasnya.

Namun, karena Cloudflare melakukan cache semua data berdasarkan header caching, dan baik apache maupun nginx mengirim header no-cache untuk 404s, Cloudflare akhirnya melakukan caching respons 404 untuk sementara waktu.

Saya telah mencari solusi untuk menambahkan tajuk sebanyak 404 secara global di apache dan nginx (secara global, untuk semua domain yang diinangi), tetapi sejauh ini belum muncul.

Adakah yang bisa membantu?

Terima kasih.

Artem Russakovskii
sumber
Pertanyaan serupa, meskipun hanya untuk apache (masih belum terjawab juga): serverfault.com/questions/331544/… .
Artem Russakovskii
Sejauh ini, saya cukup yakin bahwa Anda tidak dapat mengganti tajuk yang dikembalikan oleh penangan 404 default di apache dan nginx (tolong buktikan saya salah!). Saya dapat mengganti handler 404 dan mengarahkannya ke file PHP yang mengirimkan header seperti itu di apache, tetapi karena nginx tidak memiliki dukungan PHP pada pengaturan saya, dan pengaturan "expire -1;" pada lokasi 404 sepertinya tidak benar-benar melakukan apa-apa, saya masih bingung bagaimana melakukan ini di nginx.
Artem Russakovskii

Jawaban:

6

Tidak bisakah Anda bertahan dengan menggunakan direktif error_page, dan kemudian menangani lokasi secara terpisah dengan header yang ditambahkan?

misalnya dalam Nginx:

    server {
      ...
      error_page 404 /404.html;
      location = /404.html {
        root   /usr/share/nginx/html;
        add_header Cache-Control "no-cache" always;
      }
    }
jimmiw
sumber
1
Ada dua masalah di sini, tapi itu arah yang saya gunakan. 1. Saya tidak ingin mengganti halaman 404 default dan harus membuat aturan di setiap listenkarena locationtidak didukung di dalamnya httpsecara langsung. 2. Yang lebih penting, cuplikan Anda sebenarnya tidak berfungsi karena add_header hanya berlaku untuk 20X dan 30X ( nginx.org/en/docs/http/ngx_http_headers_module.html ). Namun, kami beruntung, karena pada versi 1.7.5 yang baru dirilis, Anda sekarang dapat menambahkan alwaysmodifer yang akan menerapkannya ke semua kode respons. Saya harus memutakhirkan nginx tetapi itu adalah tendangan yang bagus di pantat. Berhasil.
Artem Russakovskii
2
Saya memperbarui jawaban saya, Anda mungkin harus menambahkan jawaban yang menunjukkan apa yang Anda lakukan untuk menyelesaikan pertanyaan?
jimmiw
Sepertinya menghilangkan juga rootberfungsi. Jika itu dihapus, cukup banyak apa yang akhirnya saya lakukan untuk nginx.
Artem Russakovskii
Untuk apache, saya memutuskan bahwa saya sebenarnya ingin menggunakan halaman khusus, jadi saya melakukan ini: ErrorDocument 404 /path/to/my/404.php. Dan kemudian di dalam 404.php, saya melakukan <? Php // jangan cache 404 header ("Cache-Control: no-cache, must-revalidate"); // HTTP / 1.1 header ("Kedaluwarsa: Sabtu, 26 Jul 1997 05:00:00 GMT"); // Berkencan di masa lalu?>
Artem Russakovskii
Saya menandai jawaban Anda sebagai diterima. Jika seseorang ingin memberikan jawaban apache yang lebih umum nanti, atau yang nginx yang bekerja secara global daripada per server, mereka bisa terangkat.
Artem Russakovskii
5

Anda dapat melakukannya dengan cara ini juga:

map $status $cache_header {
    default <for_other_codes>;
    404     "no-cache";
}


server {

    [ ... ]

    add_header "Cache-Control" $cache_header always;

}
Xavier Lucas
sumber
Pintar. Saya mungkin akan pergi dengan solusi lain, karena sudah berfungsi dan tidak memerlukan header Cache-Control default untuk ditentukan setiap waktu, tapi ini beberapa pemikiran di luar kotak.
Artem Russakovskii
Ada tanda koma yang hilang setelah 404 "no-cache"tetapi pembatasan minimum edit 6 karakter stackexchange yang bodoh mencegah saya untuk memperbaikinya. Jelas bukan batasan yang baik untuk situs yang membahas tentang pengodean dan konfigurasi ...
nh2
3

Di apache 2.4, Anda dapat mencoba sesuatu seperti:

FileETag None
<IfModule mod_headers.c>
    Header always unset ETag "expr=%{REQUEST_STATUS} == 404"
    Header always set Cache-Control "max-age=0, no-cache, no-store, must-revalidate" "expr=%{REQUEST_STATUS} == 404"
    Header always set Pragma "no-cache" "expr=%{REQUEST_STATUS} == 404"
    Header always set Expires "Wed, 11 Jan 1984 05:00:00 GMT" "expr=%{REQUEST_STATUS} == 404"
</IfModule>

Yang alwayspenting karena ini adalah:

Anda menambahkan header ke respons non-sukses (non-2xx) yang dibuat secara lokal, seperti redirect, dalam hal ini hanya tabel yang sesuai dengan yang selalu digunakan dalam respons akhir.

Anda mengatakan semua 404, tetapi untuk referensi lengkap tentu saja mungkin masuk akal untuk membungkusnya dalam <FilesMatch>atau <LocationMatch>untuk membatasi ruang lingkup.

Saya percaya ini adalah kemampuan baru di apache 2.4 karena menggunakan exprconditional bukan dalam versi 2.2 dari dokumentasi mod_headers.

curl -I [foo] uji tanpa konfigurasi ini:

HTTP/1.1 404 Not Found
Date: Thu, 24 May 2018 17:44:29 GMT
Server: Apache/2.4.18 (Ubuntu)
Content-Type: text/html; charset=iso-8859-1

curl -I [foo] uji dengan konfigurasi ini:

HTTP/1.1 404 Not Found
Date: Thu, 24 May 2018 17:44:42 GMT
Server: Apache/2.4.18 (Ubuntu)
Cache-Control: max-age=0, no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: Wed, 11 Jan 1984 05:00:00 GMT
Content-Type: text/html; charset=iso-8859-1

Sumber:

http://httpd.apache.org/docs/current/mod/mod_headers.html

daun pohon cayleaf
sumber
0

lima sen saya tentang masalah ini -

dalam proyek PHP kami, kami memiliki beberapa 404 halaman, jadi saya memutuskan untuk melakukannya pada level PHP menggunakan fungsi header PHP ()

Nick
sumber