.htaccess 重写:如何在保留 URL 的同时提供来自不同文件夹的内容

.htaccess rewrites: how to serve content from different folders while preserving URL

提问人:Tom 提问时间:10/22/2023 最后编辑:Tom 更新时间:10/22/2023 访问量:46

问:

我正在 localhost 上开发一个站点,该站点将部署到实时主机。我正在使用 Apache 服务器,并希望使用 .htaccess 来执行内容重定向和重写。

我面临的问题是提供与 URL 中显示的内容不同的文件夹中的内容,并且我在 MOD 重写中遇到了困难。我将首先提供当前的 .htaccess 代码,然后描述文件夹结构和它之后的预期功能。

以下是我到目前为止不起作用的内容:

SetEnvIf Request_URI "^.*" LOCALHOST=https://localhost/example
SetEnvIf Request_URI "^.*" LIVEHOST=https://example.com
<If "req('Host') = 'localhost'">
    ErrorDocument 400 https://localhost/example/error/
    ErrorDocument 403 https://localhost/example/error/
    ErrorDocument 404 https://localhost/example/error/
    ErrorDocument 500 https://localhost/example/error/
</If>
<If "req('Host') != 'localhost'">
    ErrorDocument 400 https://example.com/error/
    ErrorDocument 403 https://example.com/error/
    ErrorDocument 404 https://example.com/error/
    ErrorDocument 500 https://example.com/error/
</If>
Options -MultiViews
Options -Indexes
<IfModule mod_rewrite.c>
    RewriteEngine On

#Redirect to localhost HTTPS:
    RewriteCond %{HTTP_HOST} =localhost
    RewriteCond %{HTTPS} !=on
    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
#Redirect to livehost HTTPS:
    RewriteCond %{HTTP_HOST} !=localhost
    RewriteCond %{HTTPS} !=on
    RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R=301,L]

#Strip initial www on localhost:
    RewriteCond %{HTTP_HOST} =localhost
    RewriteCond %{HTTP_HOST} ^www\.
    RewriteRule ^(.*)$ %{ENV:LOCALHOST}/$1 [R=301,L]
#Strip initial www on livehost:
    RewriteCond %{HTTP_HOST} !=localhost
    RewriteCond %{HTTP_HOST} ^www\.
    RewriteRule ^(.*)$ %{ENV:LIVEHOST}/$1 [R=301,L]

#Strip out autoversion in extension:
    RewriteRule ^((ftp|https?):\/\/)?(.*)\.((?=.*\d)[a-z\d]+)?\.(css|ico|jpe?g|m?js|json|png|gif|svg|xml|webp|webmanifest|mp4|webm|ogv)$ $1$3.$5 [L]

#Just testing on Localhost here:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^example/(.+[/]?)$ example/pages/$1 [L]


#LOCALHOST error page:
    RewriteCond %{HTTP_HOST} =localhost
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(.*)$ /example/pages/error/ [L]

#LIVEHOST error page:
    RewriteCond %{HTTP_HOST} !=localhost
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(.*)$ /pages/error/ [L]

#LOCALHOST:
    RewriteCond %{HTTP_HOST} =localhost
    RewriteRule ^ - [E=ABSOLUTE_ROOT:%{DOCUMENT_ROOT}/example/]
#LIVEHOST:
    RewriteCond %{HTTP_HOST} !=localhost
    RewriteRule ^ - [E=ABSOLUTE_ROOT:%{DOCUMENT_ROOT}/]

</IfModule>

在 localhost 上,站点根目录为:

https://localhost/example

在 livehost 上,站点根目录为:

https://example.com

在我的.htaccess文件中,我定义了:

SetEnvIf Request_URI "^.*" LOCALHOST=https://localhost/example
SetEnvIf Request_URI "^.*" LIVEHOST=https://example.com

这允许重写条件,例如:

RewriteCond %{HTTP_HOST} =localhost

和:

RewriteCond %{HTTP_HOST} !=localhost

...当在 localhost 上与实时站点上提供服务时,我需要分支以适应站点。

以下描述是相对于 localhost 环境的,但我需要适用于实时站点的代码(这就是我定义常量的原因)。

我想制作.htaccess重写,例如:

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule example/(.*)$ example/pages/$1 [L,NC]

...但我正在碰壁,试图让它发挥作用。

以下是文件夹结构:

  • 例/
    • 页面/
      • 家/
      • 错误/
      • [带或不带子文件夹结构的各种文件夹]
    • [具有可公开访问的资产的文件夹,例如,名称为 、 、 、 、cssfaviconsfontsimagesjavascript]
    • private -> [包含服务器文件和不应公开访问的文件夹的文件夹]

因此,如果客户端导航到:

example/home
example/error
example/all-other-pages

...不带或不带尾随正斜杠,则内容应从以下位置提供:

example/pages/home
example/pages/error
example/pages/all-other-pages

...无需更改 URL。

例外:如果客户端导航到站点根目录:

example

...无论是否带有尾随正斜杠,则内容应从以下位置提供:

example/pages/home

...无需更改 URL。

通常,任何没有相应导航的内容都将提供以下内容:example/*example/pages/*

example/pages/error

...无需更改 URL。(尽管这确实提出了一个关于最佳实践的问题,在最后提出。

因此,如果客户端导航到 ,并且没有文件夹,它将提供 .example/cssexample/pages/cssexample/pages/error

但是,如果客户端导航到 ,那么,如果该资产确实存在,它将为其提供服务。example/css/site.css

注意:如果服务器上没有文件夹,则导航到自身将提供内容(在这种情况下,它实际上会在不更改 URL 的情况下提供该页面上的内容)。example/pagesexample/pages/errorexample/pages/pages

不应阻止到目录的内部导航(在服务器代码中)。/pages/

公共导航将被页面文件夹资产的相同机制阻止,例如,将查找并找不到任何内容,从而重定向。example/privateexample/private/my-stuffexample/pages/private/my-stuff

最佳做法问题:重定向到错误页面时,何时应将 URL 更改为错误页面 URL,以及何时应保留该 URL,尽管提供来自 ?重定向应支持此处的最佳实践。example/pages/error

非常感谢!

php apache .htaccess 重定向 mod-rewrite

评论

0赞 CBroe 10/23/2023
“在 localhost 上,站点根目录是:https://localhost/example - 恕我直言,如果您一开始就避免这种情况,您将省去很多麻烦。在本地开发环境中设置一个合适的 VirtualHost,使用像 这样的假域,然后使用它在本地开发和测试您的站点。example.local

答: 暂无答案