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

Varnish 4升级至6.2.1后Accept请求的HTML/JSON响应异常问题

问题根因

Varnish 6.x相对Varnish 3.x调整了VCL钩子的执行时序和缓存匹配逻辑,原有代码失效主要有两个核心原因:

  1. normalize子例程没有绑定到vcl_recv阶段执行,导致Accept头归一化逻辑没有在缓存匹配前触发,第一次请求时用原始Accept头去匹配缓存(找不到就回源),但回源后写入缓存的是归一化后的Accept头对应的响应,第二次请求匹配到缓存就正常了。
  2. Varnish 6.x需要显式导入std模块才能使用std.querysort方法,旧代码没有导入模块会导致部分逻辑执行失败。

修复方案

修正后适配Varnish 6.x的完整代码

# 显式导入std模块,Varnish 6.x强制要求
import std;

sub vcl_recv {
    # 优先调用归一化逻辑,确保缓存匹配、回源前就完成Accept头处理
    call normalize;
}

sub vcl_backend_response {
    # 成功从后端获取响应头后执行
    if (!beresp.http.Vary) { # 无Vary头时直接添加
        set beresp.http.Vary = "Accept";
    } elseif (beresp.http.Vary !~ "Accept") { # 有Vary头但无Accept字段时追加
        set beresp.http.Vary = beresp.http.Vary + ", Accept";
    }
}

sub normalize {
    # 归一化Host头,移除端口号
    set req.http.Host = regsub(req.http.Host, ":[0-9]+", "");
    # 移除风险proxy头
    unset req.http.proxy;
    # 归一化查询参数
    set req.url = std.querysort(req.url);

    if (req.http.Accept) {
        if (req.http.Accept ~ "application/json") {
            set req.http.Accept = "application/json";
        } else {
            set req.http.Accept = "text/html";
        }
    }
}

验证方式

配置修改后重新加载Varnish,清理现有缓存,连续发送携带Accept: application/json的请求,首次即可正常返回JSON内容,不会出现首次返回HTML的异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 17:36:04