Apache 中不完整的重写规则

发布于 2025-01-07 18:33:56 字数 903 浏览 1 评论 0原文

我遵循 .htaccess 中的规则,

Options +FollowSymlinks
RewriteEngine on
DirectoryIndex index.php
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule ^ - [L]
RewriteRule ^captcha/(.*)$ captcha/captcha.php?cid=$1 [QSA,L]
RewriteRule ^index\.(html|php)$ / [R=301,L]
RewriteCond %{REQUEST_URI} !^/(index\.php|robots\.txt|favicon\.ico|(css|images|js|captcha)/)
RewriteRule ^(.*)$ ?get=$1 [QSA]

它应该执行以下内部操作(无需更改浏览器中的用户 URL),

/something => /index.php?get=something
/?abc=def => /index.php?abc=def
/something?some=var => /index.php?get=something&some=var

从技术上讲,它可以执行我想要的大多数操作。但它应该在不更改浏览器中用户 URL 的情况下进行重写(它应该只重定向内部)。但对于第一个和第三个示例,用户浏览器被重定向如下

/something => /something/?get=something
/something?some=var => /something/?get=something&some=var

但这不是我想要的(URL 不应该被操纵 - 它必须是内部重写)。有谁可以帮忙吗?

I've following rules in .htaccess

Options +FollowSymlinks
RewriteEngine on
DirectoryIndex index.php
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule ^ - [L]
RewriteRule ^captcha/(.*)$ captcha/captcha.php?cid=$1 [QSA,L]
RewriteRule ^index\.(html|php)$ / [R=301,L]
RewriteCond %{REQUEST_URI} !^/(index\.php|robots\.txt|favicon\.ico|(css|images|js|captcha)/)
RewriteRule ^(.*)$ ?get=$1 [QSA]

It should do the internal the following (without changing users URL in browser)

/something => /index.php?get=something
/?abc=def => /index.php?abc=def
/something?some=var => /index.php?get=something&some=var

technically it does most things I want. But it should do the rewrite without changing users URL in browser (it should only redirect internal). But for first and third example the users browser is redirected as follows

/something => /something/?get=something
/something?some=var => /something/?get=something&some=var

But that's not what I want (the URL should not be manipulated - it has to be an internal rewrite). Anyone there who can help?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

原谅我要高飞 2025-01-14 18:33:56

这是臭名昭著的尾部斜杠问题。

实际上,如果 URL 的末尾带有斜杠来访问,上面的 .htaccess 将会正常工作。即 yourdomain/something/ 但它不适用于 yourdomain/something

为什么?

如果没有尾部斜杠,apache 会将其视为文件并查找它。找不到它。它将尝试通过在末尾添加尾部斜杠来修复自身。

此时,RewriteCond %{REQUEST_URI} !^/(index\.php|rob... 已经满足,并且 RewriteRule ^(.*)$ ?get=$1 [QSA] 已经被处理过一次,并且

在 Apache 添加尾部斜杠并处理之后, URL 中已经包含了 ?get=something.htaccess 它不是内部重定向(200),因此

RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule ^ - [L]

会失败。RewriteCond %{REQUEST_URI} !^/(index\.php|rob.. . 将满足,并且 RewriteRule ^(.*)$ ?get=$1 [QSA] 将再次得到处理,

并且 apache 将在添加后立即设置临时重定向的 URL 。尾随斜杠。
此时,您的 URL 类似于 yourdomian.com/something/?get=something。这就是 URI 反映在浏览器中的原因。即,

/something => /something/?get=something
/something?some=var => /something/?get=something&some=var

但您的 index.php 实际上会看到:

/something => ?get=something/&get=something
/something?some=var => ?get=something/&get=something&some=var

Sol:

RewriteEngine on
RewriteBase /
DirectoryIndex index.php

#add these 2 lines
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule ^ - [L]

#add these
RewriteCond %{REQUEST_FILENAME} !-f 
RewriteCond %{REQUEST_URI} !\.\w+$
RewriteCond %{REQUEST_URI} !/$ 
RewriteRule (.*) /$1/ [R,L]

RewriteRule ^captcha/(.*)$ captcha/captcha.php?cid=$1 [QSA,L]

RewriteRule ^index\.(html|php)$ / [R=301,L]

RewriteCond %{REQUEST_URI} !^/(index\.php|robots\.txt|favicon\.ico|(css|images|js|captcha)/) [NC]
RewriteRule ^(.*)$ ?get=$1/ [L,QSA]
  • 检查文件是否存在。

    RewriteCond %{REQUEST_URI} !-f [OR]

  • 检查请求 URI 末尾是否没有扩展名

    RewriteCond %{REQUEST_URI} !\.\w+$

  • 检查末尾是否有尾部斜杠。

    RewriteCond %{REQUEST_URI} !/$

  • 如果满足上述条件,则使用尾部斜杠重定向当前 URL。

    RewriteRule (.*) /$1/ [R,L]
    R(重定向)默认为 302(临时重定向)。

Its the infamous trailing slash problem.

Actually your above .htaccess will work fine if an URL is accessed with a trailing slash at the end. i.e. yourdomain/something/ but it will not work for yourdomain/something

Why?

With out a trailing slash apache will treat it as a file and look for it. Failing to find it. It will try to fix itself by adding a trailing slash at the end.

By this time, the RewriteCond %{REQUEST_URI} !^/(index\.php|rob... would have already been satisfied and RewriteRule ^(.*)$ ?get=$1 [QSA] would have already been proccessed once. and the URL would already have ?get=something.

Now , after Apache adds the trailing slash, and processes the .htaccess its not an internal redirect(200). so

RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule ^ - [L]

will fail. And RewriteCond %{REQUEST_URI} !^/(index\.php|rob... will satisfy and the RewriteRule ^(.*)$ ?get=$1 [QSA] will get processed again.

And also apache will set the URL for a temporary redirect soon after adding a trailing slash.
At this point your URL looks like yourdomian.com/something/?get=something.This is why the URI gets reflected in the browser. i.e.

/something => /something/?get=something
/something?some=var => /something/?get=something&some=var

but your index.php will actually be seeing:

/something => ?get=something/&get=something
/something?some=var => ?get=something/&get=something&some=var

The Sol:

RewriteEngine on
RewriteBase /
DirectoryIndex index.php

#add these 2 lines
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule ^ - [L]

#add these
RewriteCond %{REQUEST_FILENAME} !-f 
RewriteCond %{REQUEST_URI} !\.\w+$
RewriteCond %{REQUEST_URI} !/$ 
RewriteRule (.*) /$1/ [R,L]

RewriteRule ^captcha/(.*)$ captcha/captcha.php?cid=$1 [QSA,L]

RewriteRule ^index\.(html|php)$ / [R=301,L]

RewriteCond %{REQUEST_URI} !^/(index\.php|robots\.txt|favicon\.ico|(css|images|js|captcha)/) [NC]
RewriteRule ^(.*)$ ?get=$1/ [L,QSA]
  • Checks for whether a file exists.

    RewriteCond %{REQUEST_URI} !-f [OR]

  • Checks that request URI does not have an extension at the end

    RewriteCond %{REQUEST_URI} !\.\w+$

  • Checks for whether there is a trailing slash at the end.

    RewriteCond %{REQUEST_URI} !/$

  • If the above satisfy, redirect the current URL with a trailing slash.

    RewriteRule (.*) /$1/ [R,L]
    R(redirect) by default has 302 (Temporary Redirect).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文