如何在 htaccess 中使用 IF 为某些 URL 设置状态代码

How to set status code for certain URLs with IF in htaccess

我有 https://example.com/page/1234/https://example.com/page/9876/ 这样的 URL。对于这些 URL,我想通过 htaccess (Apache 2.4) 设置某些状态代码。

我试着用

<If "%{REQUEST_URI} =~ (1234|9876)\/$">
    Header set Status "HTTP/1.1 410 Gone"
</If>

但我的代码似乎有错误,因为我没有在开发人员工具中看到新的状态代码作为响应。正确的做法应该怎样做?

PS:我不能使用 'rewriteRule' - 这种设置 410 会触发 ErrorDocument,这是我不想要的。对于这两个 URL,我只想设置状态代码。对于以本机方式获得 410 的其他 URL,应触发 ErrorDocument。

您可以将此块与 <If> 表达式一起使用,该表达式对特定 URL 模式使用默认值 ErrorDocument 410

RewriteEngine On

<If "%{REQUEST_URI} =~ m#/(1234|9876)/?$#">
    # only for above URL disable ErrorDocument
    ErrorDocument 410 default
    # set status=410
    RewriteRule . - [L,G]
</If>

使用您显示的示例,请尝试执行以下操作。请在测试您的 URL 之前清除您的浏览器缓存。

RewriteEngine ON
RewriteRule ^page/(1234|9876)/?$ - [NC,R=410,L]

Are you wanting the "normal page response" (as generated by your application), but with a 410 HTTP status?
100% correct: usual page, but with response status 410 Gone

在 Apache 中触发 410 响应将始终服务于适当的 Apache ErrorDocument。您可以做的是将 410 ErrorDocument 本身设置为相同的 URL 并以通常的方式触发 410 响应。但是,我们需要注意不要创建“rewrite-loop”。

例如:

<If "%{REQUEST_URI} =~ m#^/page/(1234|9876)/$# && %{ENV:REDIRECT_STATUS} == ''">
    # Capture the URL-path after the slash prefix
    SetEnvIf Request_URI "^/(.+)" REL_URL_PATH=

    # Dynamic ErrorDocument to the same as the requested URL
    # The slash prefix in the directive is necessary to be seen as a local URL-path
    ErrorDocument 410 /%{reqenv:REL_URL_PATH}

    # Trigger 410 Gone
    RewriteRule ^ - [G]
</If>

由于 ErrorDocument 指令中的表达式语法,这需要 Apache 2.4.13+。

检查 <If> 表达式中的 REDIRECT_STATUS 是必要的,以避免在提供错误文档本身时出现重写循环(500 响应)。

另一种方法是在您的应用程序本身中设置 410 响应代码,这是我的偏好。

旁白: 设置 Status HTTP 响应 header,这似乎是您在问题中尝试做的只是设置了一个 Status HTTP 响应header,它本身不会改变HTTP 响应状态。 (Status 响应 header 是 CGI 脚本使用的 non-standard header 来向网络服务器指示应该设置什么响应代码。)


UPDATE: in my tests if i add to htaccess only the rule Header set Status "HTTP/1.1 410 Gone", without any condition, it works like i expect: all URLs from this directory get the header 410 Gone but are still available (ErrorDocument isn't triggered).

也许您的服务器配置不同并且可能在设置 HTTP 响应的代理后面?但正如上面提到的,这只是设置了一个 Status HTTP 响应 header,它不会更改请求的 HTTP 响应代码。它在我的测试服务器上不起作用。 (如果完全使用,Status header 通常不包含协议,它只是 Header set Status "410 Gone"。)

因此,如果这对您有用,那么您只需“更正”Apache 表达式中的语法。

例如:

<If "%{REQUEST_URI} =~ m#/(1234|9876)/$#">
    Header set Status "HTTP/1.1 410 Gone"
</If>

以上匹配任何仅以 /1234//9876/ 结尾的 URL。或者,更具体地说,匹配整个 URL 使用 m#^/page/(1234|9876)/$#。这使用替代语法来分隔正则表达式(即 m#<regex>#),而不是使用斜杠(即 /<regex>/),以避免必须转义模式中的斜杠。

或者,您不需要 Apache 表达式,您可以使用 SetEnvIf 并根据环境变量有条件地设置 header。

例如:

SetEnvIf Request_URI "/(1234|9876)/$" GONE=1
Header set Status "HTTP/1.1 410 Gone" env=GONE