【问题标题】:Apache Rewrite: image directory based on HTTP hostApache Rewrite:基于 HTTP 主机的镜像目录
【发布时间】:2012-02-05 18:37:48
【问题描述】:

我的软件支持多个域名都指向服务器上的同一目录(当然,每个域名都指向不同的数据库)。所以这些域...

www.example1.com
www.example2.com
www.example3.com

...都指向...

/public_html/

在图片目录中...

/public_html/images/

我有与每个网站的主机名完全匹配的目录:

/public_html/images/www.example1.com/
/public_html/images/www.example2.com/
/public_html/images/www.example3.com/

我正在尝试让 Apache 重写请求,这样如果您直接查看图像并查看地址栏,您只会看到主机名一次。

所以请求...

http://www.example1.com/images/book.png

...由 Apache 在...处获取

/public_html/images/www.example1.com/book.png

我尝试过并在不同情况下取得成功的事情之一如下,尽管它在这种情况下不起作用:

RewriteRule ^[^/]*/images(.+) images/%{HTTP_HOST}/$1

【问题讨论】:

    标签: apache .htaccess mod-rewrite


    【解决方案1】:

    尝试将以下内容添加到站点根目录 (public_html) 中的 .htaccess 文件中

    RewriteEngine on
    RewriteBase / 
    
    #prevent looping from internal redirects
    RewriteCond %{ENV:REDIRECT_STATUS} !200
    #only rewrite gif, jpg or png
    RewriteRule ^(images)(/.+\.(gif|jpg|png))$ $1/%{HTTP_HOST}$2 [L,NC] 
    

    你的规则

    RewriteRule ^[^/]*/images(.+) images/%{HTTP_HOST}/$1
    

    没有工作,因为您在 images 之前有一个领先的 /。在 .htaccess 中,前导 / 被删除,因此规则永远不会匹配。

    【讨论】:

    • 很可能(我对此很确定,只是我旁边没有 Apache 来验证)您最终会出现 500 错误,因为您将进入重写循环:www.site1.com/images/logo.png 将是重写为/images/www.site1.com/logo.png .. 下一步它将变为/images/www.site1.com/www.site1.com/logo.png 等等——这就是你的.htaccess——你必须小心。要解决此问题 - 您需要添加一些 RewriteCond 以不重写已重写的 URL。
    • @LazyOne 你是对的。我添加了一个条件来防止循环
    • 感谢您的发帖,现在正在查看此内容,稍后会提醒您。
    • 这仅需要底部两行,所以我会接受这个作为答案。如果你可以修改它,我也会投票支持它,所以它只适用于我指定的文件类型 (gif|jpg|png),因为我想让 PHP 重写到图像目录。
    • 哦,文件类型仅适用于图像路径,我显然在其他路径中也有图像,尽管我正在学习通过阅读人们的回复做出更好的澄清。
    【解决方案2】:

    这是我为我的高性能框架所做的其中一件事情(请参阅我的简历)。

    我给你一个高级的 RewriteRule,我很确定你会有足够的材料来完成:

    创建静态域:

    static.example1.com
    static.example2.com
    static.example3.com
    

    你所有的图片都在哪里。

    从现在开始,不再有:

    www.example1.com/images/www.example1.com/picture.jpg
    www.example2.com/images/www.example2.com/picture.jpg
    www.example3.com/images/www.example3.com/picture.jpg
    

    但是

    static.example1.com/picture.jpg
    static.example2.com/picture.jpg
    static.example3.com/picture.jpg
    

    不错的网址,嗯? 现在创建一个包含所有静态文件的虚拟主机:

    <VirtualHost *>
        ServerName static.example1.com
        ServerAlias static.example2.com static.example3.com
    </VirtualHost>
    

    将您的文档根目录设置为没有虚拟主机名的基础,因此在您的情况下:

    DocumentRoot "/public_html/images"
    

    并添加这个 RewriteRule

    RewriteCond %{HTTP_HOST} ^static\.([a-zA-Z0-9\-]+)\.com$
    # Change the path, and add the request:
    RewriteRule  (.*) %{DOCUMENT_ROOT}/static.%1.com$1 [QSA,L]
    

    总而言之:

    <VirtualHost *>
        ServerName static.example1.com
        ServerAlias static.example2.com static.example3.com
        RewriteCond %{HTTP_HOST} ^static\.([a-zA-Z0-9\-]+)\.com$
        # Change the path, and add the request:
        RewriteRule  (.*) %{DOCUMENT_ROOT}/static.%1.com$1 [QSA,L]
    </VirtualHost>
    

    好吧,这并不能完全回答你的问题,所以这是简短的答案,但我不喜欢它,因为它不能帮助你做得非常(非常)好:

        RewriteCond %{HTTP_HOST} ^www\.(example1|example2|example3)\.com$
        # Change the path:
        RewriteRule (.*)(\.(css|js|txt|htc|pdf|jpg|jpeg|gif|png|ico))$ %{DOCUMENT_ROOT}/www.%1.com$1$2 [QSA,L]
    

    如果这还不够:

    两个提示:

    如果您不是在托管环境中(= 如果它是您自己的服务器并且可以修改虚拟主机,不仅是.htaccess 文件),尝试使用RewriteLog 指令:它可以帮助您追踪此类问题:

    # Trace:
    # (!) file gets big quickly, remove in prod environments:
    RewriteLog "/web/logs/mywebsite.rewrite.log"
    RewriteLogLevel 9
    RewriteEngine On
    

    我最喜欢的检查正则表达式的工具:

    http://www.quanetic.com/Regex(别忘了选择 ereg(POSIX) 而不是 preg(PCRE)!)

    【讨论】:

    • 感谢您的回复;我正在使用共享主机网络托管,所以我只能访问 .htaccess 文件。我正在尝试使用 %{HTTP_HOST} 而不是静态定义任何域名(以确保它动态扩展)并且含糊其辞地我认为您的倒数第二个代码块看起来符合潜在的工作。我会试一试,让你知道,然后再回来看看你是否对我的评论有任何跟进。
    • 好的,如果您在托管环境中,请尝试寻找您自己的服务器(我的是 20 美元/月)。
    • 更改服务器对我来说不是一个选项,我只需要弄清楚如何进行这种重写,这看起来应该很简单,因为我已经完成了一些看起来像这样的重写。
    • Olivier,对于大多数共享服务用户来说,一个问题与其说是成本,不如说是管理和运行您自己的云 VM 所涉及的学习曲线。
    • 你说得对,我很幸运能与我所知道的最好的(Linux man + administrator engineer) 之一合作。如果我一个人,我也会这么说。
    【解决方案3】:

    约翰,

    我刚刚在separate Q 上发布了您面临的一些挑战。我欢迎你的 cmets,但回到你的挑战:一个技巧,你可以使用环境变量来存储你的(最好是经过验证的)主机,例如:

    RewriteCond %{HTTP_HOST} ^www\.(host1|host2|host3\.com
    RewriteRule ^ -  [E=HOST:%1]
    

    您可能还想添加 [S] 标志以在您的规则中实现 if/then/else 逻辑。您还可以在以下规则或条件字符串(不是正则表达式模式)中使用 HOST 变量作为 %{ENV:HOST}。

    您还需要清楚地查看完整的 phpinfo() 报告,以了解您的托管服务是使用 mod_php 还是 mod_suPHP,... 接口和托管它支持 DNS 多宿主。例如,我的供应商设置 %{ENV:DOCUMENT_ROOT_REAL} 在检查文件空间时我需要使用它而不是 %{DOCUMENT_ROOT}。

    您在 DOCROOT/ 的所有 URI “到达”都采用 http://www.exampleX.com/images/book.png 的形式,因此如果您的 .htaccess 位置是您的 DOCROOT,那么您的基地是 /。所以假设上面的 ENV 设置,这些应该可以工作

    RewriteBase /
    
    RewriteCond %{HTTP_HOST} ^www\.(host1|host2|host3)\.com
    RewriteRule ^ -  [E=HOST:%1]
    
    RewriteCond %{ENV:HOST}==%{REQUEST_URI}  !^(.*?)==/image/\1
    RewriteRule ^image/(.*) image/%{ENV:HOST}/$1     [L,NS]  
    

    条件是阻止重写规则循环的垃圾。

    通用版

    上述解决方案如您所想的已经通用的解决方案。只需将 RewriteCond 正则表达式替换为与您自己的命名约定匹配的任何模式,我同意如果它是 (.*) 那么您最好放弃第一条规则并将 %{ENV:HOST} 替换为 %{HTTP_HOST}. 您需要 RewriteCond 保护防止导致 500 的循环。

    【讨论】:

    • 感谢您的发帖,现在正在查看此内容,稍后会提醒您。
    • 我接受了 Ulrich 的回答,但是当您解决了一些共享托管 Apache 问题时,我对您的单独问题投了赞成票。不幸的是,您在此处的答案静态定义了域名,这会破坏自动化,迫使我每次添加新域时手动调整 .htaccess 文件;我的目标是尽可能动态地做所有事情。您似乎有很好的洞察力,我将在以后的问题中尝试提及我不想静态定义事物,我希望留下答案的人会注意到我对 %{HTTP_HOST} 的使用。谢谢!
    • 约翰,为了便于理解,我的回答很简单,但你可以很容易地概括这一点。我会更新我的答案,告诉你怎么做。 :-) 您需要告诉我您的托管服务提供商如何使 DOCUMENT_ROOT 可访问
    • 如果您想提供帮助,我在stackoverflow.com/questions/9162845/… 有一个与此相关的简单问题。不幸的是,我所做的更改是实时的,因此我优先考虑修复实时的东西而不是在本地测试/更多时间来找出替代方法。
    猜你喜欢
    • 2013-01-24
    • 2013-12-11
    • 1970-01-01
    • 2020-09-03
    • 1970-01-01
    • 2021-06-25
    • 1970-01-01
    • 2012-01-27
    • 2019-01-17
    相关资源
    最近更新 更多