【问题标题】:Internal htaccess redirects based on combination of request and cookie not firing基于请求和 cookie 组合的内部 htaccess 重定向未触发
【发布时间】:2013-11-13 02:46:41
【问题描述】:

您好,我正在努力使用 .htaccess 实现两件事,大概每个问题都相同。

我成功地将一个名为 site-version 的 cookie 设置为 auus

如果设置了 cookie,我希望 http://www.example.comhttp://www.example.com/ (内部)重定向到 http://www.example.com/home-au.html(如果 cookie 站点版本=au)。我还想设置一个环境变量 SITE_VERSION=au。

RewriteCond %{HTTP_COOKIE} site-version=(au|us) [NC]
RewriteRule ^/?$ /home-%1.html [NC,QSA,E=SITE_VERSION:%1]

问题似乎是 RewriteRule 上的正则表达式。如果我将它设置为.*,一旦它放弃循环,它似乎会成功设置环境变量,尽管仍然没有重写请求。

如果 URL 是 http://www.example.com/a-specific-page.htmlhttp://www.example.com/another-specific-page.html 并且设置了 cookie,我想重定向到 http://www.example.com/a-specific-page-au.htmlhttp://www.example.com/another-specific-page-au.html ,即将 -au 附加到文件名。 (并设置环境变量。)

RewriteCond %{THE_REQUEST} ^(a-specific-page|another-specific-page)\.html$ [NC]
RewriteCond %{HTTP_COOKIE} site-version=au [NC]
RewriteRule ^(.*)\.html$ /$1-au.html [QSA,E=SITE_VERSION:au]

稍后在 htaccess 中我再次翻译这些 URL,所以我不想要 L 标志,但是我也尝试过:

RewriteRule ^(.*)\.html$ index.php?q=$1-au.html [QSA,E=SITE_VERSION:au,L]

我在这些主题上尝试了许多细微的变化,没有一个会触发重写。

编辑:我发现我的理解存在根本差距。 URL rewrites trigger another loop 通过.htaccess,所以我需要呈现整个文件而不是片段,这解释了为什么解决方案有效但我仍然没有得到环境变量。

RewriteCond %{HTTP_HOST} !^www\.example\.com [NC]
RewriteRule (.*) http://www.example.com/$1 [R=301,L]


########## Set the cookie if the user selects a new country #############
#  The webpage submits the existing URL plus the site-version URL parameter.   #
#  The below strips the parameter and returns to the same URL with a cookie site-version. #
#  Unless the site-version is uk (default) in which case the cookie is deleted. #

RewriteCond %{QUERY_STRING} ^.*site-version=(au|us|za|eu)$
RewriteRule (.*) $1? [co=site-version:%1:example.com:1051200:/,R,E=SITE_VERSION:%1,L]

RewriteCond %{QUERY_STRING} ^.*site-version=uk$
RewriteRule (.*) $1? [co=site-version:uk:example.com:-1:/,R,E=SITE_VERSION:uk,L]

#####################
# If the cookie is present and the URL is either a-page.html or another-page.html append -au eg, a-page-au.html #

RewriteCond %{HTTP_COOKIE} site-version=au [NC]
RewriteRule ^(a-page|another-page)\.html$ index.php?q=$1-au.html [NC,QSA,E=SITE_VERSION:au,L]

##########################
# Normal Friendly URLs rewrite, ie, cookie not detected or it isn't one of the listed URLs #

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]

【问题讨论】:

  • 我测试了第一个 RewriteRule ^/?$ /home-%1.html [NC,QSA,E=SITE_VERSION:%1],内部重定向有效。但这在浏览器的地址框中看不到,因为没有用 R 标志重定向。
  • 好的,谢谢,这也是 cookie 行吗?我在浏览器中看到了 cookie,我转到根 URL,有或没有尾随 ',我得到了非 au 页面。我想我误解了L 标志。我尝试了 RewriteRule ^/?$ /home-au.html [NC,QSA,E=SITE_VERSION:au,L] ,但 index.php?q=home-au.html 的后续规则仍然被触发(并且看起来没有设置 SITE_VERSION - 我不想担心这个问题,但如果它是诊断性的)。我认为L 会阻止任何后续重写。
  • 您最好一步完成,直接到 index.php?q=... ?

标签: php .htaccess mod-rewrite cookies


【解决方案1】:

在我的评论中,我已经测试了第一个没有 RewriteCond 的规则集,

RewriteRule ^/?$ /home-%1.html [NC,QSA,E=SITE_VERSION:%1]

我得到了这个:

http://www.example.com/ =>     http://www.example.com/home-.html

第二个规则集有一个可见错误:%{THE_REQUEST} ^(a-specific-page|another-specific-page).html$ [NC] 您可以尝试使用 %{REQUEST_URI} 而不是 %{THE_REQUEST}。 %{THE_REQUEST} 涉及 GET 或 POST 等词。

所以你可以试试这个:

RewriteCond %{HTTP_COOKIE} site-version=(au|us) [NC]
RewriteRule ^/?$ /home-%1.html [NC,QSA,E=SITE_VERSION:%1]

RewriteCond %{HTTP_COOKIE} site-version=au [NC]
RewriteRule  ^(a-specific-page|another-specific-page)\.html$ /$1-au.html [NC,QSA,E=SITE_VERSION:au]

或通过添加 R 标志设置可见重定向,如下所示:

RewriteCond %{HTTP_COOKIE} site-version=(au|us) [NC]
RewriteRule ^/?$ /home-%1.html [R,QSA,E=SITE_VERSION:%1]

RewriteCond %{HTTP_COOKIE} site-version=au [NC]
RewriteRule  ^(a-specific-page|another-specific-page)\.html$ /$1-au.html [R,NC,QSA,E=SITE_VERSION:au]

【讨论】:

  • 正如您在评论中所建议的,我将重写直接写入 index.php 并添加了 L 标志。抱歉,home-%1 重写实际上是稍后在 .htaccess 中,所以这不应该是问题,尽管我没有发现。然而,你整理的特定页面重写似乎已经清除了阻止重写工作的任何东西 - 愚蠢的错误。没有在 PHP 中使用 $site_version = getenv('SITE_VERSION') 来获取环境变量,尽管我已经非常感激了!
  • 世界上最糟糕的事情就是让你所有的梦想成真..!到目前为止的解决方案 - cookie 和重写工作,环境变量消失了。 RewriteCond %{HTTP_COOKIE} site-version=au [NC]RewriteRule ^(a-specific-page|another-specific-page)\.html$ index.php?q=$1-au.html [NC,QSA,E=SITE_VERSION:au,L]RewriteCond %{HTTP_COOKIE} site-version=(au|us) [NC]RewriteRule ^/?$ index.php?q=home-%1.html [NC,QSA,E=SITE_VERSION:%1,L]PS。当我看到它工作时,我对我的 php 相当有信心。
  • 让它使用专门针对环境变量的非 L 规则,即 RewriteCond %{HTTP_COOKIE} site-version=(au|us) [NC] RewriteRule .* - [NC,E=SITE_VERSION:%1] 无论如何我都需要这个,因为我想要 SITE_VERSION 中的 cookie,无论我是否在特定页面等上。
  • 这是对其他重写的补充(及以上)。 SITE_VERSION 似乎没有另外设置。这样做的原因是只有几个页面完全本地化,其余的只需要一个不同的电话号码、电子邮件地址和预先选择的本地化下拉菜单。
  • 如果其他人在做类似的事情,设置国家的下拉菜单会调用当前 URL document.location.pathname + '?site-version=us'。在 R 重写中,参数被 htaccess 删除,并且在标题中放置了一个 cookie。我的 cookie 设置行:RewriteCond %{QUERY_STRING} ^.*site-version=(au|us|za|eu)$ RewriteRule (.*) $1? [co=site-version:%1:example.com:1051200:/,R,E=SITE_VERSION:%1,L] 如果选择 UK(默认),则删除 cookie RewriteCond %{QUERY_STRING} ^.*site-version=uk$ RewriteRule (.*) $1? [co=site-version:uk:example.com:-1:/,R,E=SITE_VERSION:uk,L]
【解决方案2】:

完整的解决方案。这将执行以下操作:

  1. 检测 URL 参数 ?site-version,如果找到,在客户端设置一个名为 site-version 的 cookie,存储国家代码(au、eu、za 等),持续 2 年(1051200分钟)。然后它从 URL 中删除参数并让用户的浏览器再次请求原始 URL。

  2. 除了,如果 site-version=uk,这是网站的默认设置,所以 cookie 被删除(参见 co 标志中的 -1)。

特定页面有它们的本地版本。通过将国家代码添加到 URL 来访问它们。所以澳大利亚版的costs.html是costs-au.html。

  1. 如果检测到 cookie,可能是重复访问,或者可能是由于上述步骤 1 中的重定向,则检查 URL。如果 URL 是具有本地版本的页面之一,则将国家代码添加到 URL。然后将 URL 传递给 index.php - 获得美观、搜索引擎友好的 URL 的常用方法。 URL 的重写通过 .htaccess 触发另一个迭代。 (注意。据我所知,这些规则上的 E= 标志没有任何作用,因为当通过环境变量重复 .htaccess 时丢失了。如果 URL 发生更改,E= 标志实际上是无效的,因为它们一事无成。)

  2. 如果检测到 cookie,则该值将存储在名为 HTTP_SITE_VERSION 的环境变量中。 (环境变量应始终以 HTTP_ 为前缀,因为运行 suexec 的服务器会忽略不以 HTTP_ 开头的变量。suexec 是 Apache 的一项功能,允许脚本由运行 Apache 进程的用户以外的用户运行,因此在共享主机中可能很常见。)

  3. 我的 PHP 服务于更改后的 URL,即 cost-au.html,但不知道它已被更改。 (仅供参考,浏览器 URL 是 cost.html,因为这是一个内部重定向。)

  4. 对于所有页面,无论是否在列表中并有翻译,都会设置环境变量。 PHP 使用 $site_version = getenv('HTTP_SITE_VERSION') 检测到这一点(由于未设置 cookie 和变量,因此对于 UK 返回 false,而对于缺少的 var,getenv 返回 false)并显示适当的块,例如电话号码或地址。

所以,最终可行的解决方案是这样的(修复细节如下):

RewriteCond %{HTTP_HOST} !^www\.example\.com [NC]
RewriteRule (.*) http://www.example.com/$1 [R=301,L]

########## Set the cookie if the user selects a new country #############
#  The webpage submits the existing URL plus the site-version URL parameter.   #
#  The below strips the parameter and returns to the same URL with a cookie site-version. #
#  Unless the site-version is uk (default) in which case the cookie is deleted. #

RewriteCond %{QUERY_STRING} ^.*site-version=(au|us|za|eu)$
RewriteRule (.*) $1? [co=site-version:%1:example.com:1051200:/,R,E=HTTP_SITE_VERSION:%1,L]

RewriteCond %{QUERY_STRING} ^.*site-version=uk$
RewriteRule (.*) $1? [co=site-version:uk:example.com:-1:/,R,E=HTTP_SITE_VERSION:uk,L]

#############################
# Once the URLs have been rewritten, htaccess is iterated through again - re-iterating loses the environment variable to re-set it here

RewriteCond %{HTTP_COOKIE} site-version=(au|us|eu|za|uk) [NC]
RewriteRule .* - [NC,E=HTTP_SITE_VERSION:%1]

#####################
# If the cookie is present and the URL is either a-page.html or another-page.html append -au eg, a-page-au.html #

RewriteCond %{HTTP_COOKIE} site-version=au [NC]
RewriteRule ^(a-page|another-page)\.html$ index.php?q=$1-au.html [NC,QSA,E=HTTP_SITE_VERSION:au,L]


##########################
# Normal Friendly URLs rewrite, ie, cookie not detected or it isn't one of the listed URLs #

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]

我需要的修复:jacouh 建议的两个更改:

  1. 将我要匹配的字符串放入 RewriteRule 行而不是 RewriteCond。我的愚蠢疏忽。

  2. 不要分两步更改 URL,直接转到 index.php?q=.. 而不是通过新 URL,并添加 L 标志。如果 URL 被任何规则更改,则重新迭代整个 htaccess。一步完成所有事情会让事情变得更简单。

但这并不完整。重写 URL 时,触发了通过 .htaccess 的新迭代。这将删除所有环境变量并使用 REDIRECT_ 为标头添加前缀。

所以我还需要在 .htaccess 的迭代中添加环境变量的设置,而不会触发重写。 (当再次迭代 htaccess 文件时,如果有任何规则更改 URL,就会发生这种情况,环境变量会消失。很抱歉,这很冗长,但这很令人困惑。)所以我需要一个 htaccess 的迭代,它不会更改要在其中的 URL设置环境变量。因此需要添加

RewriteCond %{HTTP_COOKIE} site-version=(au|us|eu|za|uk) [NC]
RewriteRule .* - [NC,E=HTTP_SITE_VERSION:%1]

这会在 URL 被重写后在迭代中设置环境变量。嘿 presto,在我的服务器上工作。

但是当我推出它时,即使发生了重写,变量又消失了。

原来在运行suexec保护PHP的服务器上,环境变量需要以HTTP_为前缀。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-21
    • 2012-08-16
    • 2016-04-03
    • 1970-01-01
    • 2011-09-29
    • 1970-01-01
    相关资源
    最近更新 更多