Làm cách nào để thêm tiêu đề không có bộ đệm vào tất cả các trang 404 được cung cấp bởi apache và nginx?


9

Gần đây tôi đã gặp phải một vấn đề sau khi chuyển sang Cloudflare và giải pháp cơ bản là ngăn chặn Cloudflare khỏi bộ đệm phản hồi 404.

Trong thiết lập đa máy chủ cân bằng tải của chúng tôi, thỉnh thoảng xảy ra 404, nhưng chúng nhanh chóng được sửa bởi rsync (thông qua lsyncd). Trước Cloudflare, một yêu cầu lại đối với tệp 404ed sẽ nhanh chóng trở thành 200 vì rsync thực hiện công việc của mình.

Tuy nhiên, do Cloudflare lưu trữ tất cả dữ liệu dựa trên tiêu đề bộ đệm và cả apache và nginx đều không gửi tiêu đề không có bộ đệm cho 404s, Cloudflare kết thúc bộ đệm trong phản hồi 404 trong một thời gian.

Tôi đã tìm kiếm một giải pháp để thêm toàn cầu một tiêu đề như vậy cho 404 trong cả apache và nginx (trên toàn cầu, cho tất cả các tên miền được lưu trữ), nhưng cho đến nay vẫn còn trống.

Có ai giúp được không?

Cảm ơn bạn.


Câu hỏi tương tự, mặc dù chỉ dành cho apache (vẫn chưa được trả lời): serverfault.com/questions/331544/ .
Artem Russakovskii

Cho đến nay, tôi khá chắc chắn rằng bạn không thể ghi đè các tiêu đề được trả về bởi các trình xử lý 404 mặc định trong cả apache và nginx (vui lòng chứng minh tôi sai!). Tôi đã có thể ghi đè trình xử lý 404 và trỏ nó vào tệp PHP gửi các tiêu đề như vậy trong apache, nhưng vì nginx không có hỗ trợ PHP trong thiết lập của tôi và đặt "hết hạn -1;" trên vị trí 404 dường như không thực sự làm gì cả, tôi vẫn không biết làm thế nào để làm điều này trong nginx.
Artem Russakovskii

Câu trả lời:


6

Bạn không thể có được bằng cách sử dụng một lệnh error_page, và sau đó xử lý vị trí riêng biệt với tiêu đề được thêm vào?

ví dụ: trong Nginx:

    server {
      ...
      error_page 404 /404.html;
      location = /404.html {
        root   /usr/share/nginx/html;
        add_header Cache-Control "no-cache" always;
      }
    }

1
Có hai vấn đề ở đây, nhưng đó là hướng tôi đã đi. 1. Tôi không muốn ghi đè trang 404 mặc định và phải tạo quy tắc trong mỗi listenlocationkhông được hỗ trợ httptrực tiếp bên trong . 2. Quan trọng hơn, đoạn mã của bạn thực sự không hoạt động vì add_header chỉ áp dụng cho 20X và 30X ( nginx.org/en/docs/http/ngx_http_headftimemodule.html ). Tuy nhiên, chúng tôi rất may mắn, kể từ phiên bản 1.7.5 được phát hành gần đây, giờ đây bạn có thể thêm một alwaysmodifer sẽ áp dụng nó cho tất cả các mã phản hồi. Tôi đã phải nâng cấp nginx nhưng đó là một cú đá tốt vào mông. Nó hoạt động.
Artem Russakovskii

2
Tôi đã cập nhật câu trả lời của mình, có lẽ bạn nên thêm một câu trả lời cho thấy những gì bạn đã làm để giải quyết câu hỏi?
jimmiw

Hình như bỏ qua rootcông việc là tốt. Nếu điều đó bị loại bỏ, thì cuối cùng tôi đã làm cho nginx.
Artem Russakovskii

Đối với apache, tôi đã quyết định rằng tôi thực sự muốn sử dụng một trang tùy chỉnh, vì vậy tôi đã làm điều này: ErrorDocument 404 /path/to/my/404.php. Và sau đó bên trong 404.php, tôi đã làm <? Php // không lưu tiêu đề 404 ("Kiểm soát bộ đệm: không có bộ đệm, phải xác nhận lại"); // Tiêu đề HTTP / 1.1 ("Hết hạn: Thứ bảy, 26 tháng 7 năm 1997 05:00:00 GMT"); // Ngày trong quá khứ?>
Artem Russakovskii

Tôi đang đánh dấu câu trả lời của bạn là được chấp nhận. Nếu ai đó muốn cung cấp một câu trả lời apache chung chung hơn sau đó, hoặc một nginx hoạt động trên toàn cầu chứ không phải mỗi server, họ có thể được nâng cấp.
Artem Russakovskii

5

Bạn cũng có thể làm theo cách này:

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


server {

    [ ... ]

    add_header "Cache-Control" $cache_header always;

}

Tài giỏi. Tôi có lẽ sẽ đi cùng với giải pháp khác, vì nó đã hoạt động và không yêu cầu tiêu đề Cache-Control mặc định được chỉ định mỗi lần, nhưng đây là một số suy nghĩ bên ngoài hộp.
Artem Russakovskii

Có một dấu chấm phẩy bị thiếu sau 404 "no-cache"nhưng hạn chế chỉnh sửa tối thiểu 6 ký tự ngu ngốc của stackexchange ngăn tôi sửa nó. Rõ ràng không phải là một hạn chế tốt cho một trang web mà tất cả là về mã hóa và cấu hình ...
nh2

3

Trong apache 2.4, bạn có thể thử một cái gì đó như:

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>

Điều alwaysnày rất quan trọng vì đây là:

Bạn đang thêm tiêu đề vào phản hồi không thành công (không phải 2xx) được tạo cục bộ, chẳng hạn như chuyển hướng, trong trường hợp đó chỉ có bảng tương ứng luôn được sử dụng trong phản hồi cuối cùng.

Bạn đã nói tất cả 404, nhưng để tham khảo đầy đủ tất nhiên có thể có ý nghĩa để bọc nó trong một <FilesMatch>hoặc <LocationMatch>để giới hạn phạm vi.

Tôi tin rằng đây là một khả năng mới trong apache 2.4 vì sử dụng các exprđiều kiện không phải là phiên bản 2.2 của tài liệu mod_headers.

curl -I [foo] kiểm tra mà không có cấu hình này:

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] kiểm tra với cấu hình này:

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

Nguồn:

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


0

năm xu của tôi về vấn đề này -

trong dự án PHP của chúng tôi, chúng tôi có vài trang 404, vì vậy tôi quyết định thực hiện nó ở cấp độ PHP bằng cách sử dụng các hàm tiêu đề () của PHP

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.