【问题标题】:Varnish: Rewrite a URL if response is 404Varnish:如果响应为 404,则重写 URL
【发布时间】:2017-11-22 09:09:35
【问题描述】:

我很好奇如果响应是 404,在 Varnish 2.1.5 中是否有办法重写 URL?

例如。我想提取一个 URL,它可能存在也可能不存在。如果 URL 不存在,我想重写 URL 并尝试使用新的 URL。

我是 Varnish 的新手,并不完全了解请求的生命周期(如果有人知道有文章解释这一点,请分享)。

我已尝试设置一些变量和请求标头,并检查 res.status,但它们似乎在生命周期中的某个地方丢失了,并且无论如何页面 404:

if (req.http.cookie ~ "lang_pref"
      && resp.status == 404
      && req.url ~ "^\/(en|fr|de)(\/.*)?$"
      ) {
    set resp.http.Location = "https://" req.http.host regsub(req.url, "^\/(en|fr|de)\/","/");
  }

该用例用于翻译网站。示例

Website.com/french/page 可能存在也可能不存在 如果 /French/page 以 404 响应 然后尝试 /page 如果 /page 不存在 然后404

【问题讨论】:

  • 您可能需要重新考虑使用 404 重定向,因为搜索引擎可能会将其视为具有欺骗性并惩罚该网站。一个好的做法是让用户可以选择点击。现在,如果您要使用 301 重定向,那就没问题了,因为这就是 301 的目的。
  • 这很好。我如何告诉 404 它应该是 301?
  • 如果您牢记 301 或 404 的用途以及何时使用它来造福于访问者,那么您将做出最好的决定,因为搜索引擎会为搜索引擎寻找最佳结果游客。 301 表示页面已移动,这是它永久移动到的新页面。 404 表示该页面不存在或暂时不可用。在您的情况下,404 非常适合描述生成的页面内容。然后给他们一些与内容密切相关的页面链接,这将取悦访问者和搜索引擎。 404 页面不会受到惩罚,但会强制重定向。
  • 是的,我明白了。我要问的是,当页面不存在时,我如何告诉 Varnish 以 301 而不是 404 响应?

标签: varnish varnish-vcl fastly


【解决方案1】:

以下是最终适用于我的用例的方法:

sub vcl_fetch {
...
  if (beresp.status == 404 && req.url ~ "^\/(en|fr|de)(\/.*)?$") {
    error 494;
  }

  return(deliver);
}

sub vcl_error {
  # Double check i18n pages for English before 404
  if (obj.status == 494) {
      set obj.http.Location = "https://" req.http.host regsub(req.url, "^\/(en|fr|de)\/","/") "?notranslation";
      set obj.status = 302;
      return(restart);
  }
...
}

【讨论】:

    【解决方案2】:

    我写这篇文章是为了回答,否则评论会很愚蠢。 请记住,301 是永久移动的,302 是临时移动的。

    您也可以调整以使用您在帖子中所做的正则表达式。

    sub vcl_recv {
        if (req.url ~ “^/old/page”) {
            return (synth(301, “/new/page”));
        }
        if (req.url ~ “^/this/oldPage”) {
            return (synth(302, “/this/newPage”));
        }
    }
    
    sub vcl_synth {
        if (resp.status == 301 || resp.status == 302) {
            set resp.http.location = resp.reason;
            set resp.reason = "Moved";
            return (deliver);
        }
    }
    

    更新:解决 cmets。

    sub vcl_error { 
      if (obj.status == 404) { 
      set obj.status = 301; 
      set obj.http.Location = obj.response; 
      return (deliver);
    

    【讨论】:

    • 这有点帮助,但我不想保留哪些文件存在和不存在的列表。服务器后端有什么方法可以看到 404,检查 URL 并用 301 和重写的 URL 回复客户端?
    • 可能类似于if (beresp.status == 404) {maybe give client a 302 instead}
    • 您可以使用 . sub vcl_error { if (obj.status == 404) { 设置 obj.status = 301;设置 obj.http.Location = obj.response;返回(交付);
    • 很高兴它成功了 :) 如果您不介意选择此作为正确答案,那将是很棒的,或者请告知是否还有更多可以将其称为完整的。干杯
    • 看起来synth() 在 2.1.5 中的语法无效,有替代方案吗? sub vcl_error { if (obj.status == 404) 似乎也被忽略了,Apache 仍然提供默认的 404 页面
    猜你喜欢
    • 2021-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-18
    • 1970-01-01
    • 2016-08-18
    • 2013-11-24
    • 1970-01-01
    相关资源
    最近更新 更多