Apache 中不完整的重写规则
我遵循 .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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是臭名昭著的尾部斜杠问题。
实际上,如果 URL 的末尾带有斜杠来访问,上面的
.htaccess
将会正常工作。即yourdomain/something/
但它不适用于yourdomain/something
为什么?
如果没有尾部斜杠,apache 会将其视为文件并查找它。找不到它。它将尝试通过在末尾添加尾部斜杠来修复自身。
此时,
RewriteCond %{REQUEST_URI} !^/(index\.php|rob...
已经满足,并且RewriteRule ^(.*)$ ?get=$1 [QSA]
已经被处理过一次,并且在 Apache 添加尾部斜杠并处理之后, URL 中已经包含了
?get=something
。.htaccess
它不是内部重定向(200
),因此会失败。
RewriteCond %{REQUEST_URI} !^/(index\.php|rob.. .
将满足,并且RewriteRule ^(.*)$ ?get=$1 [QSA]
将再次得到处理,并且 apache 将在添加后立即设置临时重定向的 URL 。尾随斜杠。
此时,您的 URL 类似于
yourdomian.com/something/?get=something
。这就是 URI 反映在浏览器中的原因。即,但您的
index.php
实际上会看到:Sol:
检查文件是否存在。
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 foryourdomain/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 andRewriteRule ^(.*)$ ?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
). sowill fail. And
RewriteCond %{REQUEST_URI} !^/(index\.php|rob...
will satisfy and theRewriteRule ^(.*)$ ?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.but your
index.php
will actually be seeing:The Sol:
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 has302
(Temporary Redirect).