代码之家  ›  专栏  ›  技术社区  ›  Jim Rubenstein

apache mod_将子域重写为子文件夹(通过内部重定向)

  •  6
  • Jim Rubenstein  · 技术社区  · 15 年前

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

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

    我已经得到了我认为可以用的东西,而且很简单,但是……它不起作用!请求只是进入一个无限循环,并不断地将子域前缀到重新编写的请求URI中。

    我拥有的mod rewrite代码是:

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

    我在谷歌上搜索了一些关于这个的信息,但我还没有找到任何真正有效的解决方案。有人试过这个吗?或者有人有更好的主意吗?一个不涉及为每个项目制作虚拟主机的项目(我有设计师……我想每个人都会同意设计师不应该制作虚拟主机……)

    谢谢!

    以下是重写日志中的一个片段:

    [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
    

    这只是一个片段,在Apache达到重写限制、放弃并抛出错误500之前,Apache基本上会将/gnome/index.html行重写为/gnome/gnome/gnome/gnome/index.html等。

    4 回复  |  直到 10 年前
        1
  •  5
  •   Community CDub    7 年前

    几年来,我忽略了这个问题,在不同的地方又回到了这个问题上,我终于找到了一个可行的解决方案。

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

    我发现以前的参考资料 RewriteCond 在将来重写的ConditionPattern参数中,方向不可用。如果要使用上一个引用的反向引用 重写秒 指令,只能在teststring参数中使用它。

    上面的指令在第一个匹配的子域之前 重写秒 对requesturi的指令,由分隔 :: . 然后我们在 重写秒 测试字符串(regex)重新捕获子域名,然后检查以确保我们的实际requesturi不会以该子域作为文件夹,使用同一regex中的反向引用。

    这听起来比实际情况要混乱得多,而且我不能把发现答案的功劳归功于自己。我在这里找到了另一个问题的答案, %N backreference inside RewriteCond . 多亏了 Jon Lin 因为我回答了那个问题,他也不知道,我的问题!

        2
  •  1
  •   Federico Jaramillo    14 年前

    你可能想查一下

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

    它处理您遇到的documentroot问题。

    规则是这样的

    VirtualDocumentRoot /var/www/%1/
    

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

    干杯

        3
  •  0
  •   gahooa    15 年前

    一些问题:

    你说过“内部映射”——你不想使用重定向吗?

    您是否在使用同一个虚拟主机 gnome.bob.mysite.com bob.mysite.com

    您记得为创建服务器别名吗? *.bob.mysite.com ?


    这里有一个粗略的版本,您可以通过修改来工作。它将捕获子域和请求的URL,并重定向到主域,其中子域作为路径的第一部分,后跟请求的路径,后跟查询字符串。
    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
  •  0
  •   Nick Berardi    15 年前

    您是否尝试使用另一个重写规则来处理之前的规则?

    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]
    

    但我认为你最大的问题是你的服务器不明白它是以不同的名字提供服务的。

    它认为它在/gnome/目录中运行,而浏览器则在/directory中运行。所以任何相对的URL都会引起问题。

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