1

我使用 tonic.php (http://peej.github.com/tonic/) 库来创建我的 REST 资源。数据非常稳定,最好有较长的缓存时间。我设置了缓存头(使用 tonic.php 库):

$lastModified = gmdate('D, d M Y H:i:s', $_SERVER['REQUEST_TIME']) . ' GMT';                    
$expires = gmdate('D, d M Y H:i:s', ($_SERVER['REQUEST_TIME'] + $httpCacheDuration)) . ' GMT'; 
$response->addHeader('Cache-Control', 'public,max-age='.$httpCacheDuration.',must-revalidate');                    
$response->addHeader('Expires', $expires);
$response->addHeader('Last-Modified', $lastModified); 

问题是,当请求 html 时,会对 php 页面进行 cURL 调用,并将返回的 html 放入响应正文中:

$ch = curl_init();  
curl_setopt($ch, CURLOPT_URL, $url . '?identifier=' . $identifier);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

$html = curl_exec($ch); 
curl_close($ch);

$response->body = $html;

然后,此返回的页面通过 AJAX 调用对同一资源获取实际数据,但接受标头为“application/json”而不是“text/html”。AJAX 调用是用 jquery 完成的,如果我设置

cache: true

在 jquery $.ajax 中,使用 accept: text/html 调用我的资源只会将数据显示为 JSON 而不是网页 (Firefox) 或引发错误 (IE8)。代码:

switch ($format) {

    case 'html':

        $response->addHeader('Content-type', 'text/html');
        $lastModified = gmdate('D, d M Y H:i:s', $_SERVER['REQUEST_TIME']) . ' GMT';                    
        $expires = gmdate('D, d M Y H:i:s', ($_SERVER['REQUEST_TIME'] + $httpCacheDuration)) . ' GMT';                                                      
        $response->addHeader('Cache-Control', 'public,max-age='.$httpCacheDuration.',must-revalidate');                    
        $response->addHeader('Expires', $expires);
        $response->addHeader('Last-Modified', $lastModified);  
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_COOKIE, $strCookie);
        curl_setopt($ch, CURLOPT_URL, url . '?identifier=' . $identifier);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

        $html = curl_exec($ch);         
        curl_close($ch);
        $response->body = $html;
        return $response;
        break;

    case 'json':

        $result = DataManager::get($identifier);
        if (empty($result)) {
            $response->code = Response::NOTFOUND;
            return $response;
        }

        $lastModified = gmdate('D, d M Y H:i:s', $_SERVER['REQUEST_TIME']) . ' GMT';                    
        $expires = gmdate('D, d M Y H:i:s', ($_SERVER['REQUEST_TIME'] + $httpCacheDuration)) . ' GMT';                                                      
        $response->addHeader('Cache-Control', 'public,max-age='.$httpCacheDuration.',must-revalidate');                    
        $response->addHeader('Expires', $expires);
        $response->addHeader('Last-Modified', $lastModified);
        $response->addHeader('Content-type', 'application/json');
        $response->code = Response::OK;
        $response->body = json_encode($result);
        return $response;
        break;

    // we don't have a suitable format, so do a 406 response instead
    default:
        $response->code = Response::NOTACCEPTABLE;
        $response->addHeader('Content-type', 'text/plain');
        $response->body = getErrorPage(Response::NOTACCEPTABLE);
        return $response;
        break;
}

添加

$response->addHeader('Vary', 'Accept');

让它工作。然而,json 永远不会被缓存,这会导致与设置缓存相同的行为:在 Jquery ajax 调用中为 false。

如何缓存 2 种不同的表示并让浏览器为请求的接受标头显示正确的表示?

4

1 回答 1

0

答案在评论 1 中:

如果你改变 URL 怎么样?如果我理解您的问题,浏览器缓存不会根据请求中的 Accept 标头区分内容。如果您将 .json 附加到 JSON 数据包的 URL,浏览器将能够基于 URL 进行缓存。

于 2013-04-04T12:43:39.350 回答