2010-01-07 29 views
8

Sau khi tìm kiếm rất nhiều, đọc tất cả các hướng dẫn tôi đã tìm thấy và hỏi một số câu hỏi ở đây, cuối cùng tôi đã trả lời đúng (ít nhất là tôi nghĩ) về các yêu cầu HTTP nếu không có.Việc triển khai HTTP có điều kiện của tôi có được trả lời trong PHP không?

Để làm một bản tóm tắt nhanh chóng, đây là những gì tôi làm trên mỗi trang Cacheable:

session_cache_limiter('public'); //Cache on clients and proxies 
session_cache_expire(180); //3 hours 
header('Content-Type: ' . $documentMimeType . '; charset=' . $charset); 
header('ETag: "' . $eTag . '"'); //$eTag is a MD5 of $currentLanguage + $lastModified 
if ($isXML) 
    header('Vary: Accept'); //$documentMimeType can be either application/xhtml+xml or text/html for XHTML (based on $_SERVER['HTTP_ACCEPT']) 
header('Last-Modified: ' . $lastModified); 
header('Content-Language: ' . $currentLanguage); 

Ngoài ra, mỗi trang có nó là URL riêng (cho mỗi ngôn ngữ). Ví dụ: "index.php" sẽ được phân phát dưới URL "/ vi/home" bằng tiếng Anh và "/ fr/accueil" bằng tiếng Pháp.

Vấn đề lớn của tôi là trả lời "304 không được sửa đổi" thành yêu cầu HTTP nếu-không khớp và nếu được sửa đổi từ HTTP chỉ khi cần.

Các doc tốt nhất mà tôi đã tìm thấy là: http://rithiur.anthd.com/tutorials/conditionalget.php

Và đây là việc thực hiện tôi đã làm của nó (đoạn mã này được gọi là càng sớm càng tốt trên các trang có thể được lưu trữ):

$ifNoneMatch = array_key_exists('HTTP_IF_NONE_MATCH', $_SERVER) ? $_SERVER['HTTP_IF_NONE_MATCH'] : false; 
$ifModifiedSince = array_key_exists('HTTP_IF_MODIFIED_SINCE', $_SERVER) ? $_SERVER['HTTP_IF_MODIFIED_SINCE'] : false; 

if ($ifNoneMatch !== false && $ifModifiedSince !== false) 
{ 
    //Both if-none-match and if-modified-since were received. 
    //They must match the document values in order to send a HTTP 304 answer. 
    if ($ifNoneMatch == $eTag && $ifModifiedSince == $lastModified) 
    { 
     header('Not Modified', true, 304); 
     exit(); 
    } 
} 
else 
{ 
    //Only one header received, it it match the document value, send a HTTP 304 answer. 
    if (($ifNoneMatch !== false && $ifNoneMatch == $eTag) || ($ifModifiedSince !== false && $ifModifiedSince == $lastModified)) 
    { 
     header('Not Modified', true, 304); 
     exit(); 
    } 
} 

Câu hỏi của tôi là hai lần:

  • Đây có phải là cách chính xác để làm điều đó không? Ý tôi là khi nào nếu không khớp và nếu được sửa đổi được gửi, cả hai phải khớp với câu trả lời 304 và nếu chỉ một trong hai được gửi, chỉ khớp với số này là OK để gửi 304?
  • Khi được sử dụng trong ngữ cảnh được mô tả ở đây, có phải 2 đoạn trích này là bộ nhớ cache công cộng thân thiện (tôi có nghĩa là bộ nhớ cache thân thiện trên proxy Trình duyệt web)?

BTW, tôi chỉ sử dụng PHP 5.1.0+ (Tôi không hỗ trợ các phiên bản thấp hơn điều đó).

Chỉnh sửa: Đã thêm tiền thưởng ... Tôi mong đợi câu trả lời chất lượng. Đừng trả lời/bỏ phiếu nếu bạn đang đoán gì đó!

Trả lời

22
  • Nó không hoàn toàn chính xác. Vui lòng xem thuật toán: alt text http://img532.imageshack.us/img532/1017/cache.png
  • Giải pháp thân thiện với proxy, bạn có thể sử dụng Kiểm soát bộ nhớ cache: proxy-revalidate để buộc bộ nhớ cache tuân theo bất kỳ thông tin mới nào mà bạn cung cấp cho họ về tài nguyên (chỉ áp dụng cho proxy được chia sẻ) cache)

đây là chức năng mà có thể giúp:

function isModified($mtime, $etag) { 
    return !((
     isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) 
     && 
     strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $mtime 
    ) || (
     isset($_SERVER['HTTP_IF_NONE_MATCH']) 
     && 
     $_SERVER['HTTP_IF_NONE_MATCH'] == $etag 
    )) ; 
} 

tôi đề nghị bạn hãy xem bài viết sau: http://www.peej.co.uk/articles/http-caching.html

Cập nhật:

[AlexV] là thậm chí có thể nhận được nếu-không-match VÀ if-Modified-Since cùng một lúc?

Bạn chắc chắn có thể đặt cả hai.Tuy nhiên:

Nếu không có thẻ thực thể nào khớp, thì máy chủ CÓ THỂ thực hiện phương thức được yêu cầu như trường tiêu đề If-None-Match không tồn tại, nhưng PHẢI bỏ qua bất kỳ trường tiêu đề If-Modified-Since nào (s) trong yêu cầu. Tức là, nếu không có thẻ thực thể nào phù hợp, thì máy chủ PHẢI KHÔNG trả lại phản hồi 304 (Không được sửa đổi).

RFC2616 #14.26

giá trị Ví dụ (W là viết tắt của 'yếu'; đọc thêm trong RFC2616 #13.3.3):

If-None-Match: "xyzzy", "r2d2xxxx", "c3piozzzz" 
If-None-Match: W/"xyzzy", W/"r2d2xxxx", W/"c3piozzzz" 
If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT 
If-None-Match: * 

Là một trường hợp đặc biệt, giá trị "*" phù hợp với bất kỳ tổ chức hiện tại của nguồn.

+3

Lưu ý rằng phần thông số RFC2616 (HTTP1.1) 14.26 nói về cú pháp của If-None-Match. Cả câu hỏi này lẫn câu hỏi gốc đều không được phép cho nhiều giá trị etag hoặc "*". Điều đó đang được nói, giả định này có lẽ là đúng 99,9% thời gian. – MZB

+1

@Mike Bell: Vâng, tôi biết rằng ETag có thể chứa nhiều giá trị hoặc * nhưng tôi không biết bất kỳ trình duyệt nào đang sử dụng tính năng này ... Tôi tự hỏi liệu có hệ thống nào thực sự sử dụng điều này không. BTW làm thế nào để phân tích ETag khi có nhiều hơn 1 giá trị trong đó? * Có nghĩa là gì trong ETag? – AlexV

+0

@ St.Woland: Tôi đã đọc bài viết được cung cấp và xem biểu đồ của bạn (công việc tuyệt vời) và dường như nó tương ứng với phần "khác" của tôi trong đoạn thứ 2 của tôi (tôi có đúng không?). Những gì tôi thấy kỳ lạ với điều này là khi cả hai nếu không-không-phù hợp và nếu-sửa đổi-kể từ khi nhận được chỉ 1 trong 2 phải phù hợp để trả lời với 304 ... Là thậm chí có thể nhận được nếu không có trận đấu VÀ nếu -modified-since cùng một lúc? – AlexV

Các vấn đề liên quan