内部htaccess重定向基于请求和cookie未组合的组合

时间:2013-11-09 21:13:31

标签: php .htaccess mod-rewrite cookies

嗨,我正在努力用.htaccess实现两件事,大概是每件事都有同样的问题。

我已成功将名为site-version的Cookie设置为auus

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

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

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

如果网址为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中我再次翻译这些网址,所以我不想要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]

2 个答案:

答案 0 :(得分:1)

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

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

我得到了这个:

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

第二个规则集有一个可见错误:%{THE_REQUEST} ^(特定页面|另一个特定页面).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]

答案 1 :(得分:0)

完整的解决方案。这样做如下:

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

  2. 除非,如果site-version = uk,这是网站的默认设置,那么cookie将被删除(请参阅co标志中的-1)。

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

    1. 如果检测到cookie(可能是重复访问),或者可能是由于上面步骤1中的重定向,则会检查URL。如果URL是具有本地版本的页面之一,则会将国家/地区代码添加到URL。然后将URL传递给index.php - 这是获得令人愉悦的搜索引擎友好URL的常用方法。重写URL会触发.htaccess的另一次迭代。 (Nb。据我所知,E =这些规则上的标志没有达到任何效果,因为通过环境变量重复.htaccess时会丢失.E =如果URL被更改,则标志实际上无效,因为它们什么都不做。)

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

    3. 我的PHP提供更改后的URL,即costs-au.html,不知道它已被更改。 (仅供参考,浏览器网址为costs.html,因为这是内部重定向。)

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

    5. 所以,最终的,有效的解决方案是这个(修复下面的详细信息):

      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. 请勿分两步更改网址,直接转到index.php?q = ..而不是通过新网址,并添加L标记。如果任何规则更改了URL,则会重新遍历整个htaccess。一步完成所有事情会使事情变得更加简单。

      3. 但这不完整。重写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_为前缀。