【发布时间】:2022-01-10 16:47:12
【问题描述】:
由于需要 20 秒以上的繁重 API 调用,我已启用该资源的 ETag 计算,并在执行任何繁重的数据库工作之前预先计算 ETag,以便能够提前返回。使用 PHP 开发服务器可以正常工作(我可以调试代码并查看 HTTP 状态代码是否正确)并且我得到 HTTP 304,但由于某种原因,它在部署到生产环境时似乎没有生效,我想知道如何可以调试吗?
curl 调用看到正确的 If-None-Match ETag 正在发送,但我仍然得到 HTTP 200 和相同的 Etag 而不是 HTTP 304。
> if-none-match: W/"5e3f549935516374f93531655b66aaf4"
< HTTP/2 200
< date: Mon, 10 Jan 2022 16:21:55 GMT
< content-type: application/json
< server: nginx
< cache-control: private
< etag: W/"5e3f549935516374f93531655b66aaf4"
由于这在本地工作(使用 Symfony 开发服务器:./bin/console server:run),但在部署到生产环境时不行,我怀疑这与 $kernel 正在运行有关,但我遵循了 caching guide 和更改了 web/app.php 和 web/app_dev.php 以包含以下内容:
$kernel = new AppKernel('prod', false);
// enable caching
// all authorized endpoints are automatically no-cache by default
$kernel = new AppCache($kernel);
// When using the HttpCache, you need to call the method in your front controller instead of relying on the configuration parameter
Request::enableHttpMethodParameterOverride();
知道什么地方出了问题吗?
有问题的代码如下所示:
$computed = $this->getEtagAndTimestampForCatalogByUserAndType($user, $catalog_type);
$etag = $computed['etag'];
// Save the DB some work and avoid recomputing already here
if (self::matchingEtag($request, $etag)) {
return $this->json(null, Response::HTTP_NOT_MODIFIED);
}
// bla bla domain code
$responseData = doHeavyDBStuff();
$jsonResponse = $this->json($responseData);
$jsonResponse->setEtag($etag);
return $jsonResponse;
由于在 Symfony 中启用 HttpCache 类会在它们到达 AppKernel 之前删除所有缓存头,因此使用这种“提前退出”通常是不可能的,但我选择使用一个小技巧来获取 AppCache.php 中的头和将它们分配给自定义标题 (X-If-Modified-Since),然后我可以在上面的 etag 比较中进行比较:
class AppCache extends HttpCache
{
const CUSTOM_IF_NONE_MATCH_HEADER = 'x-if_none_match';
public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
{
/* Work around the fact that the caching layer removes the headers. This allows for custom caching strategies */
$request->headers->add(array(AppCache::CUSTOM_IF_NONE_MATCH_HEADER => $request->headers->get('if_none_match')));
return parent::handle($request, $type, $catch);
}
在生产中运行
- Nginx 后面的 PHP FPM。
- Symfony 3.4
- PHP 7.2
【问题讨论】:
标签: php symfony symfony-3.4 http-caching