【问题标题】:How can I redirect a subdirectory to a directory and query string?如何将子目录重定向到目录和查询字符串?
【发布时间】:2015-08-18 13:10:37
【问题描述】:

我正在尝试使用 .htaccess 和 mod_rewrite 来重定向我网站上的 URL。

我想拥有它,以便 /questions/12345/users/12345 分别重定向到 /questions/display.php?id=12345/users/display.php?id=12345

想添加一个快捷方式,有点像 Stack Exchange,其中/q/12345/6789 被重写为/questions/display.php?id=12345&refer=6789

到目前为止,通过severalsources,我得到了这个:

RewriteEngine On
RewriteRule ^users/([^/]+) /users/display.php?id=$1 [NC]
RewriteRule ^questions/([^/]+) /questions/display.php?id=$1 [NC]
RewriteRule ^q/([^/]+)/([^/]+) /questions/display.php?id=$1&referer=$2 [NC]

但是,当我导航到 /questions/12345 时,我收到 500 内部服务器错误 - 很明显,这不起作用。

查看 Apache 错误日志,它揭示了正在发生的事情:

AH00124:由于可能的配置错误,请求超出了 10 个内部重定向的限制。如有必要,使用“LimitInternalRecursion”增加限制。使用“LogLevel debug”获取回溯。

这里出了什么问题,我应该怎么做

【问题讨论】:

  • 不会正则表达式 [^/]+ 也匹配文本 display.php?id= 吗?也许您应该调整您的正则表达式以仅匹配您感兴趣的模式,即更像^users/([0-9]+) 的东西。此外,当您收到 500 错误时,您的 Apache 日志中添加了什么? 500 只是将密码返回给浏览器;您的日志应包含 500 的原因。
  • 对,所以您将/users/123/ 重写为/users/display.php?id=123,然后将其重写为/users/display.php?id=display.php?id=123,等等。
  • @ghoti - 错误在帖子中。但是,您的 0-9 想法似乎已经解决了它……不知何故。在答案中查一下。
  • 我会让你接受的。 :)

标签: php apache .htaccess mod-rewrite


【解决方案1】:

问题在于重写引擎会循环,因此您重写的内容最终会再次匹配相同的规则。您可以尝试添加一些条件来防止这种情况:

RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^users/([^/]+) /users/display.php?id=$1 [NC,L]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^questions/([^/]+) /questions/display.php?id=$1 [NC,L]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^q/([^/]+)/([^/]+) /questions/display.php?id=$1&referer=$2 [NC,L]

【讨论】:

    【解决方案2】:

    您的重定向正在捕获自身。 :-)

    注意正则表达式原子([^/]+)。这意味着“任何一个或多个不是正斜杠的字符的运行”。文本display.php?id= 匹配,所以在您的第一个请求中

    /users/123
    

    你被改写成

    /users/display.php?id=123
    

    但重定向并不止于此。新的 URL 也通过重写引擎,被写入:

    /users/display.php?id=display.php?id=123
    

    并且您重写的 URL 会不断被重写,直到您达到限制,如您的日志中所述。

    要解决这个问题,您可以使您的初始正则表达式更具限制性。

    RewriteRule ^users/([0-9]+) /users/display.php?id=$1 [NC]
    

    您还可以告诉重写引擎某个特定规则是“最后一个”规则,因此它不会重新处理该行(或通过任何其他规则运行它):

    RewriteRule ^users/([0-9]+) /users/display.php?id=$1 [NC,L]
    

    最后,如果请求的路径是文件,您可以通过告诉 Apache 不要应用重写规则来添加额外的保护:

    # Exempt requests to directories...
    RewriteCond %{REQUEST_FILENAME} !-d
    
    # Exempt requests directly to files...
    RewriteCond %{REQUEST_FILENAME} !-f
    
    # Rewrite /users/###
    RewriteRule ^users/([0-9]+) /users/display.php?id=$1 [NC,L]
    

    这有点像一个带吊带和更多吊带的解决方案,但是你想以任何可能的方式应用保护的想法是一个合理的想法。

    【讨论】:

    • 请注意,?id=123 在重写引擎循环时会丢失
    猜你喜欢
    • 1970-01-01
    • 2015-11-26
    • 1970-01-01
    • 1970-01-01
    • 2012-08-26
    • 2014-09-09
    • 2014-01-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多