【问题标题】:After Varnish Upgrade HTML/JSON Accept not workingVarnish 升级 HTML/JSON 后接受不工作
【发布时间】:2021-12-29 15:29:20
【问题描述】:

在升级 varnish 4 -> varnish-6.2.1 之后,“接受”请求未按预期响应。

如果我使用“接受:应用程序/json”发出第一个请求,它会在第二个请求时返回 HTML,然后它会继续工作。

使用 Varnish3,遵循 Snippet 使其工作 - 但不适用于 varnish6

sub vcl_backend_response {
    # Called after the response headers has been successfully retrieved from the backend.

    if (!beresp.http.Vary) { # no Vary at all
        set beresp.http.Vary = "Accept";
    } elseif (beresp.http.Vary !~ "Accept") { # add to existing Vary
        set beresp.http.Vary = beresp.http.Vary + ", Accept";
    }
}

sub normalize {
    # Normalize the header, remove the port (in case you're testing this on various TCP ports)
    set req.http.Host = regsub(req.http.Host, ":[0-9]+", "");
    # Remove the proxy header (see https://httpoxy.org/#mitigate-varnish)
    unset req.http.proxy;
    # Normalize the query arguments
    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 3: Accept JSON returns HTML

【问题讨论】:

    标签: varnish


    【解决方案1】:

    我已经测试了您的 VCL 代码,它运行良好。使sub normalize 工作所需的唯一补充如下:

    sub vcl_recv {
        call normalize;
    }
    

    PHP 测试脚本

    我编写了一个小测试脚本来复制原点的变化行为。代码如下:

    <?php
    header('Cache-Control: public, s-maxage=3600');
    $timestamp = date('Y-m-d H:i:s');
    if(isset($_SERVER['HTTP_ACCEPT']) && preg_match('/application\/json/',$_SERVER['HTTP_ACCEPT'])) {
        header('Content-Type: application/json');
        $obj = new stdClass;
        $obj->timestamp = $timestamp;
        echo json_encode($obj);
    } else {
        echo $timestamp;
    }
    

    如果在Accept 标头中找到application/json,它将返回以下输出:

    {"timestamp":"2021-11-24 07:38:35"}
    

    否则返回以下纯输出:

    2021-11-24 07:38:35
    

    VCL

    这是我为此使用的 VCL:

    vcl 4.1;
    
    import std;
    
    backend default {
        .host = "localhost";
        .port = "8080";
    }
    
    sub vcl_backend_response {
        # Called after the response headers has been successfully retrieved from the backend.
    
        if (!beresp.http.Vary) { # no Vary at all
            set beresp.http.Vary = "Accept";
        } elseif (beresp.http.Vary !~ "Accept") { # add to existing Vary
            set beresp.http.Vary = beresp.http.Vary + ", Accept";
        }
    }
    
    sub normalize {
        # Normalize the header, remove the port (in case you're testing this on various TCP ports)
        set req.http.Host = regsub(req.http.Host, ":[0-9]+", "");
        # Remove the proxy header (see https://httpoxy.org/#mitigate-varnish)
        unset req.http.proxy;
        # Normalize the query arguments
        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";
            }
        }
    }
    
    sub vcl_recv {
        call normalize;
    }
    

    如果这对您不起作用,如何调试?

    您可以运行以下varnishlog 命令来查看发生了什么:

    varnishlog -g request -I ReqHeader:Accept -i requrl -i berequrl -I RespHeader:Vary -I BereqHeader:Accept -I BerespHeader:Vary -i vcl_call -i vcl_return
    

    这里有一些示例varnishlog 输出,用于 ​​HTML 内容的现金未命中

    *   << Request  >> 34
    -   ReqURL         /test
    -   ReqHeader      Accept: */*
    -   VCL_call       RECV
    -   ReqURL         /test
    -   ReqHeader      Accept: text/html
    -   VCL_return     hash
    -   VCL_call       HASH
    -   VCL_return     lookup
    -   VCL_call       MISS
    -   VCL_return     fetch
    -   RespHeader     Vary: Accept
    -   VCL_call       DELIVER
    -   VCL_return     deliver
    **  << BeReq    >> 35
    --  BereqURL       /test
    --  BereqHeader    Accept: text/html
    --  BereqHeader    Accept-Encoding: gzip
    --  VCL_call       BACKEND_FETCH
    --  VCL_return     fetch
    --  VCL_call       BACKEND_RESPONSE
    --  BerespHeader   Vary: Accept
    --  VCL_return     deliver
    

    以下是常规 HTML 的 缓存命中 发生的情况:

    *   << Request  >> 32800
    -   ReqURL         /test
    -   ReqHeader      Accept: */*
    -   VCL_call       RECV
    -   ReqURL         /test
    -   ReqHeader      Accept: text/html
    -   VCL_return     hash
    -   VCL_call       HASH
    -   VCL_return     lookup
    -   VCL_call       HIT
    -   VCL_return     deliver
    -   RespHeader     Vary: Accept
    -   VCL_call       DELIVER
    -   VCL_return     deliver
    

    即使 HTML 版本仍在缓存中,Accept: application/json 也会导致缓存未命中:

    *   << Request  >> 32802
    -   ReqURL         /test
    -   ReqHeader      Accept:application/json
    -   VCL_call       RECV
    -   ReqURL         /test
    -   ReqHeader      Accept: application/json
    -   VCL_return     hash
    -   VCL_call       HASH
    -   VCL_return     lookup
    -   VCL_call       MISS
    -   VCL_return     fetch
    -   RespHeader     Vary: Accept
    -   VCL_call       DELIVER
    -   VCL_return     deliver
    **  << BeReq    >> 32803
    --  BereqURL       /test
    --  BereqHeader    Accept: application/json
    --  BereqHeader    Accept-Encoding: gzip
    --  VCL_call       BACKEND_FETCH
    --  VCL_return     fetch
    --  VCL_call       BACKEND_RESPONSE
    --  BerespHeader   Vary: Accept
    --  VCL_return     deliver
    

    下一次,这将导致 JSON 输出命中:

    *   << Request  >> 32805
    -   ReqURL         /test
    -   ReqHeader      Accept:application/json
    -   VCL_call       RECV
    -   ReqURL         /test
    -   ReqHeader      Accept: application/json
    -   VCL_return     hash
    -   VCL_call       HASH
    -   VCL_return     lookup
    -   VCL_call       HIT
    -   VCL_return     deliver
    -   RespHeader     Vary: Accept
    -   VCL_call       DELIVER
    -   VCL_return     deliver
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-24
      • 2016-04-08
      • 1970-01-01
      • 2016-07-05
      • 2013-02-17
      • 1970-01-01
      • 2018-08-31
      • 2017-02-20
      相关资源
      最近更新 更多