使用 .htaccess 重定向到目录中的前端或另一个目录中的 API

Redirect to frontend in directory or API in another directory using .htaccess

我有以下目录结构,其中 /root 作为我的根目录,尽管嵌套在任意数量的子目录中:

当用户导航到 example.com/dir1/root/ 时,我希望所有请求都重定向到 example.com/dir1/root/client/build/ 不更改 URL ,好像 build/ 目录内容在 root/.

此外,我希望将 example.com/dir1/root/api/* 之类的所有请求重定向到 example.com/dir1/root/api/。同样,不更改 URL.

鉴于我对 .htaccess 的工作原理知之甚少,这是我目前的尝试:

RewriteEngine on

# If an existing asset or directory is requested go to it as it is.
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]

# Redirect all requests under /api/ to the API.
RewriteCond %{REQUEST_URI} ^/api/
RewriteRule ^ api/index.php [L]

# If the requested resource doesn't exist, use index.html (html5mode)
RewriteRule ^ client/build/index.html [L]

注意:我已经搜索但没有找到针对此特定情况的任何答案,并且鉴于我对 htaccess 的了解不多,我无法很好地将现有答案拼凑在一起。

index.html is requesting resources like example.com/dir1/root/assets/style.css when this resides in /root/client/build/assets/. Essentially, I want /root/ to behave as if it's actually /root/client/build, except in the instance /root/api/ is requested.

我会将其实现为 2 个单独的 .htaccess 文件。 “根”目录(即 /dir1/root/.htaccess)中的一个处理“api”请求并将其他所有内容重写为 client/build(即“假根”)。 /dir1/root/client/build/.htaccess 中的另一个 .htaccess 文件仅处理应用程序前端内的路由。

例如:

# /dir1/root/.htaccess

RewriteEngine On

# Rewrite all requests under /api/ to the API handler "index.php"
RewriteRule ^api/(?!index\.php) api/index.php [L]

# Rewrite everything else to the "client/build/" subdirectory
RewriteRule (.*) client/build/ [L]

还有...

# /dir1/root/client/build/.htaccess

DirectoryIndex index.html

RewriteEngine On

# Front-controller
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.html [L]

子目录中 .htaccess 文件(包含 mod_rewrite 指令)的存在也有助于防止 rewrite-loop,因为它阻止了父 .htaccess 中的指令成为 re-processed(并一次又一次地将请求重写回 client/build/...)。


快速查看现有规则...

# If an existing asset or directory is requested go to it as it is.
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]

# Redirect all requests under /api/ to the API.
RewriteCond %{REQUEST_URI} ^/api/
RewriteRule ^ api/index.php [L]

# If the requested resource doesn't exist, use index.html (html5mode)
RewriteRule ^ client/build/index.html [L]

您现有规则的问题:

  • 由于第一条规则阻止任何映射到正在处理的文件或目录的请求,它也会阻止对 /dir1/root/ 本身(这是一个目录)的请求被重写为 /dir1/root/client/build/index.html.

  • 条件 RewriteCond %{REQUEST_URI} ^/api/ 永远不会成功,因为 REQUEST_URI 服务器变量包含 root-relative URL-path,即。 /dir1/root/api/.

  • 由于其他所有内容都从“根”重写为 client/build/index.html,因此也驻留在 client/build/ 中的静态资产未正确重写(它们被重写为 index.html 所以可能会导致意外响应)。

  • 您不能在“根”.htaccess 文件中执行文件系统检查,因为与 index.html 相关的静态资产只有在它们被删除后才“存在”重写。