gpt4 book ai didi

mod-rewrite - mod_rewrite 不发送变化 : Accept-Language when RewriteCond matches

转载 作者:行者123 更新时间:2023-12-04 17:13:18 26 4
gpt4 key购买 nike

我有一个重写规则重定向到 /如果没有 Accept-Language header 存在且有人试图访问 ?lang=en .它工作正常,除了返回的标题。 Vary: Accept-Language响应中缺少。

RewriteCond %{HTTP:Accept-Language} ^$  
RewriteCond %{QUERY_STRING} ^lang=en
RewriteRule ^$ http://www.example.com/? [R=301,L]
Apache 文档指定:

If a HTTP header is used in a condition this header is added to the Vary header of the response in case the condition evaluates to to true for the request. It is not added if the condition evaluates to false for the request.


条件肯定是匹配和重定向的,所以我不明白为什么 Apache 没有添加语言变化。人们可以理解为什么如果代理要缓存该 ?lang=en 这将是一个真正的问题。并始终重定向到 /无论发送的 Accept-Language header 如何。

最佳答案

在窥视了 Apache 请求处理系统的破旧功能之后,结果证明该文档有些误导......但在我开始解释之前,据我所知,在这个问题上,你受 Apache 的支配。

客户问题

首先,标题名称不会添加到变化 如果不是客户端发送的响应头。这是由于 mod_rewrite构造该 header 的值 internally .

它使用 apr_table_get() 按名称查找标题、请求的 header 表以及您提供的名称:

const char *val = apr_table_get(ctx->r->headers_in, name);

name不是表中的键,此函数将返回 NULL .这是一个问题,因为紧接着是对 val 的检查。 :
if (val) {
// Set the structure member ctx->vary_this
}
ctx->vary_this用于 per- RewriteCond基础来累积应该组装成最终 的头名称变化 标题*。由于如果没有值,则不会发生赋值或追加,因此引用(但未发送)的 header 永远不会出现在 Vary 中。 .文档没有明确说明这一点,因此它可能是也可能不是您所期望的。

*顺便说一句, NV (无变化)标志和忽略失败功能是通过设置 ctx->vary_this 实现的至 NULL ,防止将其添加到响应 header 中。

但是,您可能发送了 接受语言 ,但它是空白的。在这种情况下,空字符串会通过上面的检查,标题名称将被添加到 变化 来自 mod_rewrite从上面描述的。牢记这一点,我使用以下请求来诊断发生了什么:
User-Agent: FiddlerAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: Accept-Encoding: gzip,deflateAccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7Keep-Alive: 115Connection: keep-aliveHost: 129.168.0.123

This doesn't work either, but why? mod_rewrite definitely sets the headers when the rule and condition match (ctx->vary is an aggregate of ctx->vary_this across all checked conditions):

if (ctx->vary) {
apr_table_merge(r->headers_out, "Vary", ctx->vary);
}

这可以通过日志语句和 r->headers_out 进行验证。是生成响应头时使用的变量。既然肯定出了问题,那么规则执行后肯定会出问题。

.htaccess 问题

目前,您似乎正在 .htaccess 中定义您的规则。 ,或 <Directory>部分。这意味着 mod_rewrite在 Apache 的 fixup 阶段运行,它用来实际执行重写的机制非常困惑。让我们暂时假设没有外部重定向,因为即使没有它你也会遇到问题(稍后我将讨论重定向的问题)。

执行重写后,模块在请求处理中实际映射到文件为时已晚。相反,它做的是将自己分配为请求的“内容”处理程序,当请求到达该点时,它执行对 ap_internal_redirect() 的调用。 .这会导致创建一个新的请求对象,该对象不包含 headers_out来自原始表。

假设 mod_rewrite不会导致进一步的重定向,响应是从新的请求对象生成的,它永远不会分配给它适当的(原始) header 。可以通过在每个服务器的上下文中工作(在主配置中或在 <VirtualHost> 中)来解决这个问题,但是......

重定向问题

不幸的是,事实证明无论如何它基本上都无关紧要,因为即使我们确实使用了 mod_rewrite在服务器上下文中,发生重定向时响应采用的路径仍会导致模块设置的 header 被丢弃。

当 Apache 收到请求时,它会通过一系列函数调用到达 ap_process_request() .这反过来调用 ap_process_request_internal() ,其中发生了大部分重要的请求解析步骤(包括调用 mod_rewrite)。它返回一个整数状态代码,在您重定向的情况下,它恰好设置为 301。

大多数请求返回 OK (其值为 0),立即导致 ap_finalize_request_protocol() .然而,那是 not the case here :
if (access_status == OK) {
ap_finalize_request_protocol(r);
}
else {
r->status = HTTP_OK;
ap_die(access_status, r);
}
ap_die()做一些额外的操作(比如将响应代码返回到 301),在这种特殊情况下以调用 ap_send_error_response() 结束。 .

幸运的是,这终于是问题的根源。虽然看起来像,但事情并不是“向后”,这会导致原始标题的破坏。甚至还有评论 in the source :
if (!r->assbackwards) {
apr_table_t *tmp = r->headers_out;

/* For all HTTP/1.x responses for which we generate the message,
* we need to avoid inheriting the "normal status" header fields
* that may have been set by the request handler before the
* error or redirect, except for Location on external redirects.
*/
r->headers_out = r->err_headers_out;
r->err_headers_out = tmp;
apr_table_clear(r->err_headers_out);

if (ap_is_HTTP_REDIRECT(status) || (status == HTTP_CREATED)) {
if ((location != NULL) && *location) {
apr_table_setn(r->headers_out, "Location", location);
}
//...
}
//...
}

请注意 r->headers_out被替换,并清除原始表。该表包含预期在响应中显示的所有信息,因此现在丢失了。

结论

如果您不重定向并在每个服务器的上下文中定义规则,则一切似乎都可以正常工作。然而,这不是你想要的。我可以看到一个潜在的解决方法,但我不确定它是否可以接受,更不用说需要重新编译服务器了。

至于 Vary: Accept-Encoding ,我只能假设它来自不同的模块,该模块的行为方式允许标题潜入。我也不知道为什么 Gumbo尝试时没有问题。

作为引用,我正在查看 2.2.14 和 2.2 trunk source code ,我正在修改和运行 Apache 2.2.15。相关代码部分中的版本之间似乎没有任何显着差异。

关于mod-rewrite - mod_rewrite 不发送变化 : Accept-Language when RewriteCond matches,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3698363/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com