You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Symfony 6.3+PHPUnit测试ETag缓存:二次请求未返回304问题

问题:Symfony 6.3测试ETag缓存时无法返回304状态码

在Symfony 6.3环境下使用PHPUnit 10.4测试端点ETag缓存功能时出现异常:控制器在实际HTTP客户端及调试场景中表现正常,但测试里第二次请求携带首次获取的ETag作为If-None-Match头时,返回200状态码而非预期的304。尝试调用客户端的disableReboot或reboot方法无效果,怀疑测试环节存在配置遗漏。

测试代码

public function testCache() {
    $client = static::createClient();

    $client->request('GET', '/test?param=123');

    $response = $client->getResponse();

    $this->assertResponseIsSuccessful();

    $etag = $response->getEtag();

    $client->request('GET', '/test?param=123', [
        'headers' => [
            'If-None-Match' => $etag
        ]
    ]);

    $this->assertResponseStatusCodeSame(Response::HTTP_NOT_MODIFIED); // 实际返回200而非304
}

响应示例

HTTP/1.1 200 OK
Age:              1
Cache-Control:    public
Content-Length:   76
Content-Type:     application/json
Date:             Mon, 19 Feb 2024 22:03:45 GMT
Etag:             "bc4a907bcc4d3e601993f1646938d2a2"
X-Content-Digest: en1c1a61e2a1702c01d3298b4b204a21dd
X-Robots-Tag:     noindex
X-Symfony-Cache:  GET /test?param=123&headers%5BIf-None-Match%5D=%22bc4a907bcc4d3e601993f1646938d2a2%22&param2=321: stale, valid, store

可能的原因及解决办法

1. 测试环境未启用HTTP缓存

Symfony测试客户端默认不启用HTTP缓存,需手动配置。创建客户端时传入启用缓存的参数:

$client = static::createClient([], [
    'HTTP_CACHE' => true,
]);

2. 请求头传递方式错误

Symfony测试客户端传递自定义头时,需使用HTTP_前缀格式,或者调整参数传递位置。修改第二次请求的头信息传递方式:

$client->request('GET', '/test?param=123', [], [], [
    'HTTP_IF_NONE_MATCH' => $etag
]);

3. 缓存存储未共享

测试环境可能使用临时缓存驱动,导致两次请求无法共享缓存数据。在config/packages/test/framework.yaml中配置统一的缓存驱动:

framework:
    cache:
        app: cache.adapter.array
        system: cache.adapter.array

4. ETag生成逻辑不一致

检查控制器中ETag的生成逻辑,确保相同请求参数下生成的ETag完全一致,避免因额外参数、时间戳等因素导致ETag变化。

修改后的测试代码示例

public function testCache() {
    $client = static::createClient([], ['HTTP_CACHE' => true]);

    // 首次请求获取ETag
    $client->request('GET', '/test?param=123');
    $this->assertResponseIsSuccessful();
    $etag = $client->getResponse()->getEtag();

    // 携带If-None-Match头发起第二次请求
    $client->request('GET', '/test?param=123', [], [], [
        'HTTP_IF_NONE_MATCH' => $etag
    ]);

    $this->assertResponseStatusCodeSame(Response::HTTP_NOT_MODIFIED);
}

内容的提问来源于stack exchange,提问作者Grokking

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 10:27:47