Apache mod_rewrite子域到子文件夹(通过内部重定向)

时间:2020-11-29 11:25:10

I'm trying to write a set of mod_rewrite rules that allow my users to utilize a single folder for doing development on different projects, and not have to mess with adding vhosts for every single project.

我正在尝试编写一组mod_rewrite规则,允许我的用户使用单个文件夹在不同的项目上进行开发,而不必为每个项目添加vhosts。

My idea to accomplish this, is to set up a "Global VHost" for every single user who needs this ability (only 3-4), the vhost would be something like: .my-domain.com. From there, I want to promote my users to write code as if it were on a domain, and not in a sub folder. For example, if bob was working on a project named 'gnome,' I'd like the URL bob (and anyone else on our internal network) loads to get to this project to be: http://gnome.bob.my-domain.com. But, what I'd like Apache to do, is recognize that "gnome" is a "project" and thus map the request, internally, to bob.my-domain.com/gnome/.

我想要实现这个目标,就是为每个需要这种能力的用户设置一个“全球VHV”(只有3-4个),vhost就像:.my-domain.com。从那里,我想促进我的用户编写代码,就像它在域上,而不是在子文件夹中。例如,如果bob正在处理一个名为“gnome”的项目,我希望URL bob(以及我们内部网络上的其他任何人)加载到这个项目:http://gnome.bob.my- domain.com。但是,我希望Apache能做的是,认识到“gnome”是一个“项目”,因此在内部将请求映射到bob.my-domain.com/gnome/。

I've got what I thought would work, and it's quite simple, but..it doesn't work! The request just goes into an infinite loop and keeps prefixing the sub domain onto the re-written request URI.

我有我认为会起作用的东西,而且很简单,但是......它不起作用!该请求只是进入一个无限循环,并将子域前缀保留在重写的请求URI上。

The mod rewrite code i have is:

我的mod重写代码是:

RewriteEngine On

RewriteCond %{HTTP_HOST}    ^([^.]+)\.bob\.my-domain\.com
RewriteCond %{REQUEST_URI}  !^/%1.*
RewriteRule ^(.*)$      /%1/$1 [L]

I've googled around a bit about this, but I've yet to find any real solutions that work. Has anyone tried this - or maybe, does anyone have a better idea? One that doesn't involve making a virtual host for every project (I've got designers..I think everyone would agree that a designer shouldn't be making virtual hosts..)

我已经在谷歌上搜索了一下,但我还没有找到任何有效的解决方案。有没有人试过这个 - 或许,有没有人有更好的主意?一个不涉及为每个项目制作虚拟主机(我有设计师......我想每个人都会同意设计师不应该制作虚拟主机......)

Thanks!

Here is a snippet from the rewrite_log:

这是rewrite_log的一个片段:

[rid#838dc88/initial] (3) [perdir /home/bob/http/] strip per-dir prefix: /home/bob/http/index.html -> index.html
[rid#838dc88/initial] (3) [perdir /home/bob/http/] applying pattern '^(.*)$' to uri 'index.html'
[rid#838dc88/initial] (4) [perdir /home/bob/http/] RewriteCond: input='gnome.bob.my-domain.com' pattern='^([^.]+)\.bob\.my-domain\.com' => matched
[rid#838dc88/initial] (4) [perdir /home/bob/http/] RewriteCond: input='/index.html' pattern='!^/%1.*' => matched
[rid#838dc88/initial] (2) [perdir /home/bob/http/] rewrite 'index.html' -> '/gnome/index.html'
[rid#838dc88/initial] (1) [perdir /home/bob/http/] internal redirect with /gnome/index.html [INTERNAL REDIRECT]
[rid#8392f30/initial/redir#1] (3) [perdir /home/bob/http/] strip per-dir prefix: /home/bob/http/gnome/index.html -> gnome/index.html
[rid#8392f30/initial/redir#1] (3) [perdir /home/bob/http/] applying pattern '^(.*)$' to uri 'gnome/index.html'
[rid#8392f30/initial/redir#1] (4) [perdir /home/bob/http/] RewriteCond: input='gnome.bob.my-domain.com' pattern='^([^\.]+)\.bob\.my-domain\.com' => matched
[rid#8392f30/initial/redir#1] (4) [perdir /home/bob/http/] RewriteCond: input='/gnome/index.html' pattern='!^/%1.*' => matched
[rid#8392f30/initial/redir#1] (2) [perdir /home/bob/http/] rewrite 'gnome/index.html' -> '/gnome/gnome/index.html'
[rid#8392f30/initial/redir#1] (1) [perdir /home/bob/http/] internal redirect with /gnome/gnome/index.html [INTERNAL REDIRECT]
[rid#8397970/initial/redir#2] (3) [perdir /home/bob/http/] add path info postfix: /home/bob/http/gnome/gnome -> /home/bob/http/gnome/gnome/index.html

This is just a snippet, there are a few 10s or 100 or so lines of apache basically rewriting /gnome/index.html to /gnome/gnome/gnome/gnome/gnome/index.html, etc before apache hits its rewrite limit, gives up, and throws error 500

这只是一个片段,在apache达到其重写限制之前,有几个10或100左右的apache基本上重写/gnome/index.html到/gnome/gnome/gnome/gnome/gnome/index.html等,放弃,并抛出错误500

4 个解决方案

#1


After a few years of ignoring this problem and coming back to it at various points, I finally found a workable solution.

经过几年忽略这个问题,并在不同的点回到它,我终于找到了一个可行的解决方案。

RewriteEngine on
RewriteCond %{HTTP_HOST} ^([^.]+)\.bob\.my-domain\.com
RewriteCond %1::%{REQUEST_URI} !^(.*?)::/\1/
RewriteRule ^(.*)$  /%1/$1 [L]

What I found was that back-references for previous RewriteCond directions are not available in the ConditionPattern parameter of future RewriteConditions. If you want to use a back-reference from a previous RewriteCond directive, you can only use it in the TestString parameter.

我发现在以后的RewriteConditions的ConditionPattern参数中没有以前的RewriteCond方向的反向引用。如果要使用先前RewriteCond指令的反向引用,则只能在TestString参数中使用它。

The above directives prepend the sub-domain matched in the 1st RewriteCond directive to the RequestURI, delimited by ::. What we then do in the RewriteCond Test String (regex) is re-capture the sub-domain name, then check to make sure our actual RequestURI doesn't begin with that sub-domain as a folder using a back reference within the same regex.

上述指令将第一个RewriteCond指令中匹配的子域添加到RequestURI,由::分隔。然后我们在RewriteCond测试字符串(正则表达式)中做的是重新捕获子域名,然后检查以确保我们的实际RequestURI不以该子域开始作为在同一个正则表达式中使用后向引用的文件夹。

This sounds a lot more confusing than it really is, and I can't take the credit for discovering the answer. I found the answer as a response to another question here, %N backreference inside RewriteCond. Thanks to Jon Lin for answering that question, and unknown to him, my question too!

这听起来比实际上更令人困惑,我不能因为发现答案而受到赞誉。我找到了答案作为对另一个问题的回答,在RewriteCond中%N反向引用。感谢Jon Lin回答这个问题,而且他也不知道,我的问题也是如此!

#2


You might want to check

你可能想检查一下

http://httpd.apache.org/docs/2.2/vhosts/mass.html

it deals with the DocumentRoot problem that you were experiencing.

它处理您遇到的DocumentRoot问题。

Rule goes something like this

规则就是这样的

VirtualDocumentRoot /var/www/%1/

You can change the %1 for whatever suits you (http://httpd.apache.org/docs/2.0/mod/mod_vhost_alias.html)

您可以为适合您的任何内容更改%1(http://httpd.apache.org/docs/2.0/mod/mod_vhost_alias.html)

Cheers

#3


Some Questions:

You said "map internally" -- do you NOT want to use a redirect?

你说“内部地图” - 你不想使用重定向吗?

Are you using the same VirtualHost for gnome.bob.mysite.com and bob.mysite.com

您是否在gnome.bob.mysite.com和bob.mysite.com上使用相同的VirtualHost

Did you remember to create a ServerAlias for *.bob.mysite.com?

你还记得为* .bob.mysite.com创建ServerAlias吗?


Here is a rough version that you could modify to work. It will capture the subdomain and requested URL, and do a redirect to the main domain with the subdomain as the first part of the path, followed by the requested path, followed by the query string.

ServerName www.mysite.com
ServerAlias *.mysite.com

RewriteCond %{HTTP_HOST} ^([a-zA-Z0-9-]+)\\.mysite.com$
RewriteRule ^/(.*)       http://www.mysite.com/%1/$1        [R=301,L]',    

#4


Have you tried using another rewrite rule to process the one before it?

您是否尝试过使用其他重写规则来处理之前的规则?

RewriteEngine On

RewriteCond %{HTTP_HOST}                       ^([^.]+)\.bob\.my-domain\.com
RewriteCond %{REQUEST_URI}                     !^/%1.*
RewriteRule ^(.*)$                             /%1/$1 [C]    
RewriteRule ^/(.*)\.bob\.my-domain\.com/(.*)   /$1/$2 [L]

But I think your bigger problem is the fact that your server doesn't understand it is getting served under a different name.

但我认为你的更大问题是你的服务器不理解它以不同的名称提供服务。

It thinks it is running in the /gnome/ directory while the browser things it is running in the / directory. So any relative URL's that you have are going to cause issues.

它认为它正在/ gnome /目录中运行,而浏览器正在/目录中运行。因此,您拥有的任何相对URL都会导致问题。

What you need is a filter that will run all the URL's in your page through a processor and change them from /gnome/ to /.

您需要的是一个过滤器,它将通过处理器运行您页面中的所有URL,并将它们从/ gnome /更改为/。

#1


After a few years of ignoring this problem and coming back to it at various points, I finally found a workable solution.

经过几年忽略这个问题,并在不同的点回到它,我终于找到了一个可行的解决方案。

RewriteEngine on
RewriteCond %{HTTP_HOST} ^([^.]+)\.bob\.my-domain\.com
RewriteCond %1::%{REQUEST_URI} !^(.*?)::/\1/
RewriteRule ^(.*)$  /%1/$1 [L]

What I found was that back-references for previous RewriteCond directions are not available in the ConditionPattern parameter of future RewriteConditions. If you want to use a back-reference from a previous RewriteCond directive, you can only use it in the TestString parameter.

我发现在以后的RewriteConditions的ConditionPattern参数中没有以前的RewriteCond方向的反向引用。如果要使用先前RewriteCond指令的反向引用,则只能在TestString参数中使用它。

The above directives prepend the sub-domain matched in the 1st RewriteCond directive to the RequestURI, delimited by ::. What we then do in the RewriteCond Test String (regex) is re-capture the sub-domain name, then check to make sure our actual RequestURI doesn't begin with that sub-domain as a folder using a back reference within the same regex.

上述指令将第一个RewriteCond指令中匹配的子域添加到RequestURI,由::分隔。然后我们在RewriteCond测试字符串(正则表达式)中做的是重新捕获子域名,然后检查以确保我们的实际RequestURI不以该子域开始作为在同一个正则表达式中使用后向引用的文件夹。

This sounds a lot more confusing than it really is, and I can't take the credit for discovering the answer. I found the answer as a response to another question here, %N backreference inside RewriteCond. Thanks to Jon Lin for answering that question, and unknown to him, my question too!

这听起来比实际上更令人困惑,我不能因为发现答案而受到赞誉。我找到了答案作为对另一个问题的回答,在RewriteCond中%N反向引用。感谢Jon Lin回答这个问题,而且他也不知道,我的问题也是如此!

#2


You might want to check

你可能想检查一下

http://httpd.apache.org/docs/2.2/vhosts/mass.html

it deals with the DocumentRoot problem that you were experiencing.

它处理您遇到的DocumentRoot问题。

Rule goes something like this

规则就是这样的

VirtualDocumentRoot /var/www/%1/

You can change the %1 for whatever suits you (http://httpd.apache.org/docs/2.0/mod/mod_vhost_alias.html)

您可以为适合您的任何内容更改%1(http://httpd.apache.org/docs/2.0/mod/mod_vhost_alias.html)

Cheers

#3


Some Questions:

You said "map internally" -- do you NOT want to use a redirect?

你说“内部地图” - 你不想使用重定向吗?

Are you using the same VirtualHost for gnome.bob.mysite.com and bob.mysite.com

您是否在gnome.bob.mysite.com和bob.mysite.com上使用相同的VirtualHost

Did you remember to create a ServerAlias for *.bob.mysite.com?

你还记得为* .bob.mysite.com创建ServerAlias吗?


Here is a rough version that you could modify to work. It will capture the subdomain and requested URL, and do a redirect to the main domain with the subdomain as the first part of the path, followed by the requested path, followed by the query string.

ServerName www.mysite.com
ServerAlias *.mysite.com

RewriteCond %{HTTP_HOST} ^([a-zA-Z0-9-]+)\\.mysite.com$
RewriteRule ^/(.*)       http://www.mysite.com/%1/$1        [R=301,L]',    

#4


Have you tried using another rewrite rule to process the one before it?

您是否尝试过使用其他重写规则来处理之前的规则?

RewriteEngine On

RewriteCond %{HTTP_HOST}                       ^([^.]+)\.bob\.my-domain\.com
RewriteCond %{REQUEST_URI}                     !^/%1.*
RewriteRule ^(.*)$                             /%1/$1 [C]    
RewriteRule ^/(.*)\.bob\.my-domain\.com/(.*)   /$1/$2 [L]

But I think your bigger problem is the fact that your server doesn't understand it is getting served under a different name.

但我认为你的更大问题是你的服务器不理解它以不同的名称提供服务。

It thinks it is running in the /gnome/ directory while the browser things it is running in the / directory. So any relative URL's that you have are going to cause issues.

它认为它正在/ gnome /目录中运行,而浏览器正在/目录中运行。因此,您拥有的任何相对URL都会导致问题。

What you need is a filter that will run all the URL's in your page through a processor and change them from /gnome/ to /.

您需要的是一个过滤器,它将通过处理器运行您页面中的所有URL,并将它们从/ gnome /更改为/。