对文件夹进行 POST 会被接收为 GET

问题描述 投票:0回答:1

我在不使用框架的情况下在 php 中制作 api,当我使用邮递员将 POST 发送到文件夹时,index.php 上的

$_SERVER['REQUEST_METHOD']
是 GET。

我的文件夹组织示例:

📂api
 ┗ 📂engine
    ┗ 📜index.php
    ┗ 📜history.php

如果我发帖到

http://localhost/project/api/engine

index.php 上的

$_SERVER['REQUEST_METHOD']
是 GET,但如果我发一个 POST 到

http://localhost/project/api/engine/

(末尾附加斜杠)

$_SERVER['REQUEST_METHOD']
是 POST

我尝试使用chatgpt提供的一些规则创建一个.htaccess(因为我对.htaccess一无所知),但没有任何效果

当我请求末尾没有斜杠的文件夹时,如何使 POST 成为 POST?

我的环境:
Windows 11
XAMPP 作为服务器
PHP 8.2.4

apache .htaccess post request
1个回答
0
投票

默认情况下,Apache mod_dir 将尾部斜杠附加到物理目录,以便“修复”*1 URL。这是通过 301(永久)重定向来实现的。这里的“问题”是 301(和 302)往往会被用户代理/浏览器在重定向(第二次)请求上转换为

GET
请求。而这自然会丢失POST数据。 (旁白:创建 307 和 308 是为了解决此问题,因为它们通过重定向保留请求方法。尽管如此,不言而喻,您永远不应该链接/请求重定向的 URL。 )

请求

/project/api/engine/
直接“工作”,因为没有发生301重定向。

*1 尾部斜杠是 必需的,以便从该目录提供

DirectoryIndex
文档(即
index.php
)(这是您所期望的)。

您可以使用

DirectorySlash Off
指令阻止 mod_dir 附加尾部斜杠。但是,您仍然需要手动附加尾部斜杠(通过内部重写),否则您的
DirectoryIndex
文档 (
index.php
) 将不会被提供。您还需要确保禁用自动生成的目录列表 (mod_autoindex),否则即使该目录中存在
DirectoryIndex
文档,也会在响应中返回目录列表。

因此,您可以在

/project/api/.htaccess
文件中这样做(以限制受影响的目录):

# /project/api/.htaccess

# Disable auto generated directory listings (mod_autoindex)
Options -Indexes

# Prevent mod_dir appending a trailing slash to directories
DirectorySlash Off

# Need to use mod_rewrite ...
RewriteEngine On

# Internally append the trailing slash to directories
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*[^/])$ $1/ [L]

请注意,您需要清除所有本地缓存,因为默认情况下通常会缓存 301(永久)重定向。


替代方案 - 更改文件结构

但是,我会避免禁用

DirectorySlash
,因为这可能会导致其他问题,具体取决于您的系统。无论如何,不建议使用非描述性
index.php
文件。相反,我会稍微重新考虑您的文件结构,也许只是从您的请求中删除
.php
扩展名。

例如,文件结构可以如下所示:

📂project
  ┗ 📂api
     ┗ 📜engine.php
     ┗ 📜history.php

您的 API 请求将采用

/project/api/engine
的形式(以及
/project/api/history
,而不是
/project/api/engine/history.php
)。

在您的

/project/api/.htaccess
中,您只需要一些代码即可通过内部重写附加
.php
扩展。例如:

# /project/api/.htaccess

# Need to use mod_rewrite ...
RewriteEngine On

# Append the ".php" file extension where necessary:
RewriteCond $1 !(\.php|/)$
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}.php -f
RewriteRule (.*) $1.php [L]

您也可以阻止对

.php
文件本身的任何直接请求。

© www.soinside.com 2019 - 2024. All rights reserved.