我正在尝试编写一个简单的 REST API,目前正在尝试正确配置我的.htaccess
文件。
我想要实现的目标如下:
- 必须
RewriteRule
将请求定向到实际的 RestController - 捕获所有未
RewriteRule
在之前明确提供服务并出现 FITTING 错误的 请求RewriteRule
应答复针对未使用前者处理的任何文件、子目录或子目录中的文件的请求403
- 应回答针对任何不存在的文件或子目录的请求
404
到目前为止我所取得的成就是:
- ✅ 提供不存在的文件、子目录和子目录中的文件
404
- ✅ 在没有适当的情况下提供现有文件和子目录
RewriteRule
403
- ❌ 将有效的 API 请求转发到正确的端点(在我添加最后一条
403
规则后它停止工作) - ❌
403
在没有适当的情况下为子目录中的现有文件提供服务RewriteRule
- 例如。当我尝试访问时domain.com/subdir/existingfile.pdf
,它实际上显示了我不想要的文件。
由于子目录可以动态创建,因此我希望处理 403 中的所有子目录和文件,而无需手动指定它们。
这是我目前的.htaccess
:
Options -Indexes
RewriteEngine on
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# REST mappings
RewriteRule ^json$ RestController.php?key=json [L,nc,qsa]
RewriteRule ^file/(.*)$ RestController.php?key=file&id=$1 [L,nc,qsa]
RewriteRule ^actions$ RestController.php?key=actions&id=none [L,nc,qsa]
RewriteRule ^actions/(.*)$ RestController.php?key=actions&id=$1 [L,nc,qsa]
# catch all non-matched requests and throw 404 or 403 accordingly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ - [R=404,NC,L]
RewriteRule ^ - [R=403,NC,L]
因为
RestController.php
是一个文件而不是您的“映射”之一,所以最后一条规则将无条件提供 403。您需要例外和
RestController.php
/或使用该END
标志(Apache 2.4 中的新功能),而不是L
,以阻止 mod_rewrite 指令的所有进一步处理。(该L
标志仅停止当前轮的处理。在目录上下文中,例如.htaccess
,重写的 URL 将传递到下一个处理阶段,然后在第二阶段处理最后一个规则。)您也不需要明确的规则来服务 404,因为默认情况下会发生这种情况。仅当请求映射到文件(或目录)时才需要规则,以便为 403 提供服务。
例如,
RestController.php
最后一个规则块中有一个例外:L
将非 3xx 状态与该标志一起使用时,不需要该标志R
。您不一定需要检查目录(第二个条件),除非您碰巧在该目录中有文档
DirectoryIndex
(例如index.php
或index.html
)(但为什么要检查?)。当请求没有文档的目录时,mod_autoindex 自动提供 403 错误DirectoryIndex
。或者,或者同时,使用
END
前面规则中的标志:NC
这里不需要标志。另请注意,我删除了$
in^file/(.*)$
,因为它不是必需的(正则表达式默认是贪婪的)。在旁边:
如果您标准化端点,您的“映射”可以减少为单个规则,即。始终是
key
andid
参数,并且id
可以为空(不是“无”),无论如何您都需要对其进行验证(根据您的规则, 和 都是有效请求,但会产生不同的目标)/actions
。/actions/
然后,您在 PHP 脚本中验证目标。例如:
这确实意味着
/json/<foo>
和/file
将被成功重写RestController.php
(否则将被您的原始规则忽略),但这些请求无论如何都应该由您的 REST API 验证处理。或许.*
真的应该如此.+
。