【问题标题】:Apache Clean-Urls with MultiViews enabled启用多视图的 Apache Clean-Urls
【发布时间】:2012-12-20 09:39:47
【问题描述】:

我正在尝试启用 Clean-Urls,启用 MultiViews。

我拥有的所有页面都在根文件夹本身中。

我正在努力实现以下目标:

(current-status -> what I am trying to achieve)

 1. foo.com/services.php -> foo.com/services
 2. foo.com/services == foo.com/services/
 3. foo.com/services.php/second-level/ == foo.com/services/second-level

services不是文件夹,我爆$_SERVER['PATH_INFO']得到二级路径数据。

我已经实现了第一个,但是当我启用MultiViews,使用.htaccess 文件并写入重写时它失败了。

Options +Indexes +FollowSymLinks -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.*) $1.php [L]

(这显然会失败,因为它会将请求更改为 services/second-level.php)。 我知道我可以在.htaccess 中编写多个重写,并有条件地重定向。

但奇怪的事实是,在实时环境(共享主机)上,它正在工作,没有根文件夹中的任何.htaccess 文件。由于是共享主机,无法读取配置文件。

关于我应该更改什么配置(apache.conf*.conf)以实现上述目标有什么想法吗?

如果重要的话,我使用的是Apache/2.2.22,这个问题在更新后开始出现。

【问题讨论】:

  • 我不认为你想要这个:foo.com/services.php -> foo.com/services,但是这个:foo.com/services -> foo.com/services.php。在浏览器的地址中显示一个“丑陋”的 URL 没有多大意义,其中资源显示为 (foo.com/services.php),而隐藏“漂亮”的 URL foo.com/services,除非有非常特殊的原因。 ¿ 有吗?
  • @FelipeAlamedaA :我想要 Clean URL 本身。刚刚更新了问题以使其更清晰。

标签: php apache .htaccess mod-rewrite apache2


【解决方案1】:

虽然 MultiViews 可用于此目的,不要向 PHP 文件添加任意 MIME 类型以让 MultiViews 为它们提供服务,例如 accepted answer 和 Internet 上的许多其他来源建议:

# Bad code - don't do this!
Options +MultiViews
AddType application/x-httpd-php .php

我在https://stackoverflow.com/a/24598848/1709587 上详细解释过的这个hack 看似有效,但实际上已被破坏;每当服务器收到带有不包含*/*Accept 标头的请求时,它将失败。

相反,干净的解决方案是使用 MultiviewsMatch 指令告诉 Apache 提供 .php 文件是有效的,而不管请求的 AcceptAccept-Language 标头如何:

# Good code - use this instead!
Options +MultiViews
<Files "*.php">
    MultiviewsMatch Any
</Files>

【讨论】:

    【解决方案2】:

    不带 .php 扩展名且不使用 MultiViews 的干净 URL。

    一个灵活的 Web 环境,使用 mod_userdirmod_rewrite 支持虚拟子域。

    允许以下网址布局

    • /var/www/sites/www/services.php
      • http://foo.bar/services.php/second-level/
      • http://foo.bar/services/second-level/
      • http://www.foo.bar/services/second-level/
      • http://127.0.0.1/services/second-level/
    • /var/www/sites/www/admin/login.php
      • http://foo.bar/admin/login.php/foo
      • http://foo.bar/admin/login/foo
      • http://www.foo.bar/admin/login/foo

    注意在前面加或不加 www。是平等的,因为 www。今天过时了... 但是现在您也可以通过在/var/www/sites/ 中添加一个文件夹来托管虚拟子域(记住 DNS)

    • /var/www/sites/images/imgpass.php
      • http://images.foo.bar/imgpass.php/photo.jpg
      • http://images.foo.bar/imgpass/photo.jpg
      • http://www.images.foo.bar/imgpass/photo.jpg
      • http://127.0.0.1/~images/imgpass/photo.jpg

    ...等等,但如果 /var/www/sites/images/imgpass 本身存在则跳过。

    我使用的是多用户环境,每个用户都有自己的 webroot 和子域。

    /etc/apache2/sites-enabled/foo.bar.conf:

    <VirtualHost *:80>
      ServerAdmin my-email-id
      ServerName foo.bar
      ServerAlias 127.0.0.1 *.foo.bar
    
      # The default web-root if no subdomain is given
      DocumentRoot /var/www/sites/www/
    
      UserDir /var/www/sites/*
      <Directory /var/www/sites/*>
                Order allow,deny
                Allow from all
                DirectoryIndex index.php index.html
                Options -MultiViews -Indexes
    
                # MultiViews workaround with 1 level subdir support
                RewriteEngine On
    
                RewriteCond %{REQUEST_FILENAME} !-d
                RewriteCond %{REQUEST_FILENAME} !-f
                RewriteCond %{REQUEST_FILENAME} ^(\/var\/www\/sites\/.+(\/[^\/]+){2}).*
                RewriteCond %1.php -f
                RewriteRule ^\/var\/www\/sites\/(.+)((?:\/[^\/]+){2})(.*) /~$1$2.php$3 [L]
    
                RewriteCond %{REQUEST_FILENAME} !-d
                RewriteCond %{REQUEST_FILENAME} !-f
                RewriteCond %{REQUEST_FILENAME} ^(\/var\/www\/sites\/.+(\/[^\/]+){1}).*
                RewriteCond %1.php -f
                RewriteRule ^\/var\/www\/sites\/(.+)((?:\/[^\/]+){1})(.*) /~$1$2.php$3 [L]
       </Directory>
    
       # Force all requests in background to UserDir compatible requests
       RewriteEngine on
       RewriteMap      lc                      int:tolower
    
       RewriteCond     %{REQUEST_FILENAME}     !^/~
       RewriteCond     %{HTTP_HOST}            ^(www\.)?(.+)\.foo\.bar$
       RewriteRule     /(.*)                   /~${lc:%2}/$1                   [PT,L]
    
    </VirtualHost>
    

    此代码不是 testet,因为我的文件系统结构与最初的示例完全不同。 所以我即时转换了我的配置以适应这个示例结构。

    注意配置不完整。您需要根据自己的需要自行调整。

    【讨论】:

      【解决方案3】:

      终于知道怎么解决了。

      这可行,完全删除 .htaccess 文件,并更改 Virtual Directory 以保留以下设置:

      <VirtualHost *:80>
          ServerAdmin my-email-id
          ServerName foo.bar
          DocumentRoot /var/www/sites/foo/
      
          <Directory /var/www/sites/foo/>
              Options +FollowSymLinks +MultiViews +Indexes
              DirectoryIndex index.php
              AddType application/x-httpd-php .php
          </Directory>
      
      </VirtualHost>
      

      这有助于我让所有页面都能正常工作,就像它们在服务器上工作一样,没有任何重写条件。

      【讨论】:

      • 使用 MultiViews 方法时,我经常在 Apache 的错误日志中看到错误“没有可接受的变体”。你也是这样吗?
      • 我在使用“+MultiViews”时没有运气。添加“AddType application/x-httpd-php .php”对我来说是个窍门。谢谢。
      • 这种方法被破坏了。请参阅stackoverflow.com/q/16357933/1709587 了解它导致的问题,并查看stackoverflow.com/a/24598848/1709587 了解为什么以及如何解决它(明确引用此答案)。
      猜你喜欢
      • 2013-10-22
      • 1970-01-01
      • 2015-01-07
      • 1970-01-01
      • 1970-01-01
      • 2013-09-26
      • 2011-11-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多