我有这样的结构:
site.com/api/index.php
。当我将数据发送到 site.com/api/
时没有问题,但我想如果 api 也能在没有尾部斜杠的情况下工作会更好,如下所示:site.com/api
。这会导致 301 重定向,从而丢失数据(因为数据未转发)。我尝试了我能想到的所有重写,但无法避免重定向。这是我当前的重写规则(尽管可能无关紧要)。
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^api/(.*)$ api/index.php [L]
我可以在不使用尾部斜杠的情况下使此网址正常工作并维护帖子数据吗?
一些重写不起作用:(全部仍然重定向)
RewriteRule ^api$ api/index.php [L]
RewriteRule ^api/*$ api/index.php [L]
您首先需要关闭目录斜杠,但是尾部斜杠非常重要,这是有原因的:
关闭尾部斜杠重定向可能会导致信息泄露。考虑这样一种情况:mod_autoindex 处于活动状态
并且(Options +Indexes)
设置为有效资源(例如,DirectoryIndex
),并且没有为该 URL 定义其他特殊处理程序。在这种情况下,带有尾部斜杠的请求将显示index.html
文件。但是不带尾部斜杠的请求将列出目录内容。index.html
这意味着访问不带尾部斜杠的目录将仅列出目录内容,而不是提供默认索引(例如
index.php
)。因此,如果您想关闭目录斜杠,则必须确保在内部重写回尾随斜杠。
DirectorySlash Off
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*[^/])$ /$1/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^api/(.*)$ api/index.php [L]
第一条规则确保尾部斜杠被附加到末尾,尽管只是在内部。与从外部重定向浏览器的 mod_dir 不同,内部重写对浏览器是不可见的。然后下一条规则执行 api 路由,并且由于第一条规则,保证有一个尾部斜杠。
如果您不想使用 Jon Lin 提供的解决方案(重新配置所有指向目录的 URL),您可以使用以下代码(注意正则表达式中的 ? - 它基本上表示“api”后面的尾部斜杠是选修的)。我还没有测试过,但它应该可以正常工作:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^api/?(.*)$ api/index.php [L]
我的 Next.js 示例有额外的注释,还有额外的
RewriteOptions AllowNoSlash
用于 UX 链接,例如 /login
,可以正常工作,而不是丑陋的 /login/
:
<VirtualHost *:443>
ServerName my.local
# For basePath+assetPrefix in next.config.js.
Alias "/agent" "/www/sites/my"
<Directory "/www/sites/my">
Require all granted
# Prevent 301 redirect for directories without slashes.
DirectorySlash Off
# mod_dir doesn't help - it expects a traling slash.
# DirectoryIndex index.html
# Prevent directory listing - it is a security flaw / UX unfriendly.
Options -Indexes
# For trailingSlash:true + skipTrailingSlashRedirect:true in next.config.js.
RewriteEngine On
# LogLevel rewrite:trace8
# Transfrom logical paths: /login => /login/index.html.
RewriteOptions AllowNoSlash
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*)$ $1/index.html [L]
</Directory>
ProxyPass "/api" "http://192.168.1.2:8080/api"
ProxyPassReverseCookieDomain "192.168.1.2" "api.local"
</VirtualHost>