强制为mod_rewrite的RewriteRule替代提供URL路径 [英] Force a URL-path for mod_rewrite's RewriteRule Substitution

查看:50
本文介绍了强制为mod_rewrite的RewriteRule替代提供URL路径的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当使用mod_rewrite的RewriteRule执行重写时,将根据文件系统上是否存在替换的根目录来评估替换,并猜测是URL还是文件系统路径.这是来自文档的相关部分:

URL路径

请注意,mod_rewrite尝试通过检查路径的第一段是否存在于文件系统的根目录中来猜测是指定了文件系统路径还是URL路径.例如,如果您指定/www/file.html Substitution 字符串,那么除非根目录中存在名为www的目录,否则这将被视为URL路径.您的文件系统(或者,在相对于文档根目录使用.htaccess文件中的重写的情况下),在这种情况下,它将被视为文件系统路径.

所以我的问题是,如何将URI重写为文件系统中存在根目录 的URI,但我希望将其视为URL?

除了指定完整的URL,还有其他方法吗?同样根据文档:

绝对URL

如果指定了绝对URL,则mod_rewrite将检查主机名是否与当前主机匹配.如果是这样,则将方案和主机名删除,并将得到的路径视为URL路径.否则,将对给定的URL执行外部重定向.

所以我可以这样解决:

RewriteRule ^/example.html$ %{REQUEST_SCHEME}://%{HTTP_HOST}/var/example.html

这对于代码的可读性而言并不理想.我真的很想能够做到:

RewriteRule ^/example.html$ /var/example.html

/var存在时,不将其评估为文件系统路径.似乎没有一个标志可以强制执行此操作.还有一个风险,就是稍后会创建匹配路径并违反规则,我想避免这种冗长的情况.

我也知道我可以通过将规则放在.htaccess中而不是Apache配置中来解决此问题,因此搜索是从文档根目录进行的,如上面的引用中所述,但这不是我想要的

还有其他方法吗?

更新

由于杜尚·巴吉克(Dusan Bajic)的回答,事实证明[PT]标志可以在这里提供帮助,正如我错过了文档第一引号的句子中所暗示的那样:

如果希望将其他URL映射指令(例如Alias)应用于结果URL路径,请使用[PT]标志,如下所述.

通过使用[PT]标志(此处的文档),这将导致替换被视为URI而不是[文件路径]",这听起来像它应该回答这个问题,但是不幸的是,使用[PT]标志还有其他含义:

  • 这意味着[L],因此不会发生对重写规则的进一步处理.
  • 这将导致URL映射再次运行,这是它的目的,并且在仅希望强制将替代解释为URL路径时可能并不理想.

因此,我现在暂时不回答这个问题,因为所需的解决方案不会出现上述问题.可接受的答案将导致替换被视为URL路径,就像替换的根目录不存在于文件系统中一样,而不会以任何其他方式影响处理.

更新2

我意识到,当URL在文档根目录中时,另一种解决方案是始终在替换开始时添加%{DOCUMENT_ROOT}.所以它是这样的:

RewriteRule ^/example.html$ %{DOCUMENT_ROOT}/var/example.html

这也会阻止以后处理URL的规则起作用,因此它与[PT]选项相似,而不会导致URL映射再次运行.

解决方案

您忽略了引用段落的最后一句:

如果您希望应用其他URL映射指令(例如Alias) 到生成的URL路径,请使用[PT]标志,如下所述.

似乎它不适用于您的问题(非常明智的问题),但是如果您进一步深入研究the documentation:

URL-path

Note that mod_rewrite tries to guess whether you have specified a file-system path or a URL-path by checking to see if the first segment of the path exists at the root of the file-system. For example, if you specify a Substitution string of /www/file.html, then this will be treated as a URL-path unless a directory named www exists at the root or your file-system (or, in the case of using rewrites in a .htaccess file, relative to your document root), in which case it will be treated as a file-system path.

So my question is, how do I rewrite to a URI, where the root directory does exist in the file-system, but I want it to be treated as a URL?

Is there any way other than specifying the full URL? Also according to the docs:

Absolute URL

If an absolute URL is specified, mod_rewrite checks to see whether the hostname matches the current host. If it does, the scheme and hostname are stripped out and the resulting path is treated as a URL-path. Otherwise, an external redirect is performed for the given URL.

So I can get round it like this:

RewriteRule ^/example.html$ %{REQUEST_SCHEME}://%{HTTP_HOST}/var/example.html

Which is not ideal for readability of the code. I really want to be able to do:

RewriteRule ^/example.html$ /var/example.html

Without that being evaluated as a file-system path when /var exists. There doesn't seem to be a flag to force this. There is also a risk of a matching path being created later and breaking rules, which I would like to avoid without so much verbosity.

I am also aware I can solve this by putting the rules in .htaccess instead of the Apache config, so the search is made from the document root as described in the quote above, but that's not what I'm looking for.

Is there any other way?

Update

Thanks to Dusan Bajic's answer, it turns out the [PT] flag can help here, as hinted at in the sentence I missed off the first quote from the docs:

If you wish other URL-mapping directives (such as Alias) to be applied to the resulting URL-path, use the [PT] flag as described below.

By using the [PT] flag (docs here), it will cause the substitution "to be treated as a URI instead [of a file-path]", which sounds like it should answer this question, but unfortunately there are other implications to using the [PT] flag:

  • It implies [L] so no further processing of rewrite rules will occur.
  • It causes URL mapping to run again, which is what it is for, and may not be desirable when simply wishing to force a substitution to be interpreted as a URL-path.

So I am leaving this question open without an accepted answer for now, as the desired solution will not have the above issues. An accepted answer will cause the substitution to be treated as a URL-path, as it would be if the root directory of the substitution did not exist in the file-system, without affecting the processing in any other way.

Update 2

I realised that another option to help with this, when the URL is within the document root, is to always add %{DOCUMENT_ROOT} at the start of the substitution. So it makes it like this:

RewriteRule ^/example.html$ %{DOCUMENT_ROOT}/var/example.html

This also prevents later rules that process the URL from working though, so it's similar to the [PT] option without causing the URL mapping to run again.

解决方案

You overlooked the last sentence of the quoted paragraph:

If you wish other URL-mapping directives (such as Alias) to be applied to the resulting URL-path, use the [PT] flag as described below.

It seems like it does not apply to your (very sensible btw.) question, but if you dig further into [PT]:

The target (or substitution string) in a RewriteRule is assumed to be a file path, by default. The use of the [PT] flag causes it to be treated as a URI instead.

For example (if you turn on LogLevel debug rewrite:trace6):

RewriteRule ^/boo$ /opt/mock.png

Will log:

[...] init rewrite engine with requested uri /boo
[...] applying pattern '^/boo$' to uri '/boo'
[...] rewrite '/boo' -> '/opt/mock.png'
[...] local path result: /opt/mock.png
[...] go-ahead with /opt/mock.png [OK]

but

RewriteRule ^/boo$ /opt/mock.png [PT]

Will log:

[...] init rewrite engine with requested uri /boo
[...] applying pattern '^/boo$' to uri '/boo'
[...] rewrite '/boo' -> '/opt/mock.png'
[...] forcing '/opt/mock.png' to get passed through to next API URI-to-filename handler

这篇关于强制为mod_rewrite的RewriteRule替代提供URL路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆