如何添加带有清漆的尾部斜杠?

时间:2014-11-14 01:37:11

标签: regex varnish varnish-vcl

我想在所有带有清漆的网址上添加一个尾部斜杠(通过301重定向)。

然而,我很惊讶我无法在任何地方找到任何关于网络的信息。

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

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,不要添加/)

2 个答案:

答案 0 :(得分:1)

以下是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

答案 1 :(得分: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");
        }
    }
}

这对我来说绝对不错,我希望它也可以对其他人有所帮助。