【问题标题】:How to add trailing slash with varnish?如何用清漆添加斜杠?
【发布时间】:2015-01-11 08:20:51
【问题描述】:

我想用清漆(通过 301 重定向)为所有 URL 添加一个尾部斜杠。

我很惊讶我在任何地方都找不到任何关于在线的信息。

这是我得到的最接近的,但显然被破坏了,因为它不考虑查询字符串或任何带有 .在里面。

if (req.url !~ "/$") {
  return (synth (751, ""));
}

...

sub vcl_synth {
  if (resp.status == 750) {
    set resp.status = 301;
    set resp.http.Location = "http://www.example.com" + req.url;
    return(deliver);
  }
}

我要考虑的测试用例

example.com/xyz?query=string -> www.example.com/xyz/?query=string(加www,加/)

example.com/api/latest.json -> www.example.com/api/latest.json(加www,不加/)

【问题讨论】:

  • 查看堆栈溢出 - 许多网站不需要斜杠。
  • 我不想要你的意见,我想回答我的问题。
  • 所以你想重定向example.com/xyz?query=stringexample.com/xyz/?query=stringexample.com/api/latest.jsonexample.com/api/latest.json/等等?您能否编辑您的问题,以提供有关您希望重定向如何执行的具体示例。
  • 我澄清了“之前和之后”的例子。
  • 那么你怎么知道什么时候添加斜线,什么时候不添加?如果您的任何文件夹包含点 (xyz.abc),则添加尾部斜杠不起作用。这会在后端处理得更好。

标签: regex varnish varnish-vcl


【解决方案1】:

基于上述varnish 3 的解决方案,这里是varnish 4 的解决方案,用于处理不带斜线的超时问题。我只是想在清漆请求中附加斜杠,没有其他花哨的东西。

因为没有尾随斜杠,我注意到超时问题,尤其是在 /wp-admin 上。而/wp-admin/ 工作正常。但现在在default.vcl 进行以下更新后,一切正常。

如果您遇到超时问题并且您进行了更改但仍然遇到相同的问题,请考虑刷新浏览器的缓存,并在浏览器的私人窗口中打开 URL 并尝试在您没有的其他浏览器中尝试'不使用。

sub vcl_recv {
    if (req.url ~ "(?:/[^./]+$)|(?:/[^.?]+\?)") {
        // no . in last path segment before optional query string

        //add trailing slash to directory URL for instance wp-admin will be replaced with wp-admin/
        if (req.url !~ "/$" && req.url !~ "\?") {
            // no trailing slash and no query string
            set req.url = req.url + "/";
        } else if (req.url ~ "[^/]\?") {
            // no trailing slash and with query string, preserve it
            set req.url = regsub(req.url, "([^?]+)\?.*", "\1") + 
                            "/" + regsub(req.url, "[^?]+(\?.*)", "\1");
        }
    }
}

这对我来说绝对没问题,我希望它也可以帮助其他人。

【讨论】:

    【解决方案2】:

    这是 Varnish 3 的解决方案,您可以将其翻译成 Varnish 4。我自己没有 Varnish 4:

    sub vcl_recv {
        if (req.http.Host !~ "^www\." || (
               req.url !~ {"(?x)
                   (?:/$)         # last character isn't a slash
                   |              # or
                   (?:/\?)        # query string isn't immediately preceded by a slash
               "} &&
               req.url ~ {"(?x)
                   (?:/[^./]+$)   # last path segment doesn't contain a . no query string
                   |              # or
                   (?:/[^.?]+\?)  # last path segment doesn't contain a . with a query string
               "})
        ) {
            error 720;
        }
    }
    
    sub vcl_error {
        if (obj.status == 720) {
            set obj.status = 301;
    
            set obj.http.Location = "http://";
            set obj.http.Host = req.http.Host;
            if (obj.http.Host !~ "^www\.") {
                // for www. prefix
                set obj.http.Host = "www." + obj.http.Host;
            }
            set obj.http.Location = obj.http.Location + obj.http.Host;
    
            if (req.url ~ "(?:/[^./]+$)|(?:/[^.?]+\?)") {
                // no . in last path segment before optional query string
                if (req.url !~ "/$" && req.url !~ "\?") {
                    // no trailing slash and no query string
                    set obj.http.Location = obj.http.Location + req.url + "/";
                } else if (req.url ~ "[^/]\?") {
                    // no trailing slash and with query string, preserve it
                    set obj.http.Location = obj.http.Location +
                      regsub(req.url, "([^?]+)\?.*", "\1") +
                      "/" +
                      regsub(req.url, "[^?]+(\?.*)", "\1");
                } else if (obj.http.Host != req.http.Host) {
                    // trailing slash rule met, handle missing www. scenario
                    set obj.http.Location = obj.http.Location + req.url;
                }
            } else if (obj.http.Host != req.http.Host) {
                // last path segment contains a . so handle missing www. scenario
                set obj.http.Location = obj.http.Location + req.url;
            }
            set obj.response = "Moved Permanently";
        }
    }
    

    我有一个 Varnish 测试用例文件,它也可以测试您感兴趣的各种 URL:

    varnishtest "Testing adding trailing slash"
    
    server s1 {
        rxreq
        txresp -body "hello world"
    } -repeat 4 -start
    
    varnish v1 -vcl+backend {
        include "${pwd}/26921577.vcl";
    } -start
    
    client c1 {
        txreq -url "/document/" -hdr "Host: www.example.com"
        rxresp
    
        expect resp.status == 200
        expect resp.body == "hello world"
    } -run
    
    client c2 {
        txreq -url "/document" -hdr "Host: www.example.com"
        rxresp
    
        expect resp.status == 301
        expect resp.http.Location == "http://www.example.com/document/"
    } -run
    
    client c3 {
        txreq -url "/document/" -hdr "Host: example.com"
        rxresp
    
        expect resp.status == 301
        expect resp.http.Location == "http://www.example.com/document/"
    } -run
    
    client c4 {
        txreq -url "/document" -hdr "Host: example.com"
        rxresp
    
        expect resp.status == 301
        expect resp.http.Location == "http://www.example.com/document/"
    } -run
    
    client c5 {
        txreq -url "/xyz/?query=string" -hdr "Host: www.example.com"
        rxresp
    
        expect resp.status == 200
        expect resp.body == "hello world"
    } -run
    
    client c6 {
        txreq -url "/xyz?query=string" -hdr "Host: www.example.com"
        rxresp
    
        expect resp.status == 301
        expect resp.http.Location == "http://www.example.com/xyz/?query=string"
    } -run
    
    client c7 {
        txreq -url "/xyz/?query=string" -hdr "Host: example.com"
        rxresp
    
        expect resp.status == 301
        expect resp.http.Location == "http://www.example.com/xyz/?query=string"
    } -run
    
    client c8 {
        txreq -url "/xyz?query=string" -hdr "Host: example.com"
        rxresp
    
        expect resp.status == 301
        expect resp.http.Location == "http://www.example.com/xyz/?query=string"
    } -run
    
    client c9 {
        txreq -url "/api/latest.json" -hdr "Host: www.example.com"
        rxresp
    
        expect resp.status == 200
        expect resp.body == "hello world"
    } -run
    
    client c10 {
        txreq -url "/api/latest.json" -hdr "Host: example.com"
        rxresp
    
        expect resp.status == 301
        expect resp.http.Location == "http://www.example.com/api/latest.json"
    } -run
    
    client c11 {
        txreq -url "/api/latest.json?query=string" -hdr "Host: www.example.com"
        rxresp
    
        expect resp.status == 200
        expect resp.body == "hello world"
    } -run
    
    client c12 {
        txreq -url "/api/latest.json?query=string" -hdr "Host: example.com"
        rxresp
    
        expect resp.status == 301
        expect resp.http.Location == "http://www.example.com/api/latest.json?query=string"
    } -run
    
    varnish v1 -expect client_req == 12
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-01-16
      • 2018-06-29
      • 2012-01-12
      • 2015-02-06
      • 1970-01-01
      • 1970-01-01
      • 2015-10-23
      相关资源
      最近更新 更多