I'm making an api in php without using a framework and when I send a POST using postman to a folder the $_SERVER['REQUEST_METHOD']
on index.php is a GET.
Example of my folder organization:
📂api
┗ 📂engine
┗ 📜index.php
┗ 📜history.php
If i make a POST to
http://localhost/project/api/engine
the $_SERVER['REQUEST_METHOD']
on index.php is GET, but if i make a POST to
http://localhost/project/api/engine/
(additional slash at end) the $_SERVER['REQUEST_METHOD']
is POST
I tried to create a .htaccess with some rules provided by chatgpt (because I don't know anything about .htaccess) but nothing worked
How can i make the POST be a POST when i request the folder without the slash at the end?
My environment :
Windows 11
XAMPP as server
PHP 8.2.4
By default, Apache mod_dir appends the trailing slash to the physical directory in order to "fix"*1 the URL. This is achieved with a 301 (permanent) redirect. The "problem" here is that a 301 (and 302) tends to get converted to a GET
request by the user-agent/browser on the redirected (2nd) request. And this naturally loses the POST data. (Aside: A 307 and 308 were created to resolve this issue as they preserve the request method through the redirect. Although, it goes without saying, you should never be linking/requesting a URL that redirects in the first place.)
Requests to /project/api/engine/
directly "work" because no 301 redirect occurs.
*1 The trailing slash is required in order to serve the DirectoryIndex
document (ie. index.php
) from that directory (which is what you are expecting).
You can prevent mod_dir from appending the trailing slash with the DirectorySlash Off
directive. However, you still need to manually append the trailing slash (with an internal rewrite), otherwise your DirectoryIndex
document (index.php
) is not going to be served. You also need to ensure that auto-generated directory listings (mod_autoindex) are disabled, otherwise a directory listing will be returned in the response even if a DirectoryIndex
document is present in that directory.
So, you could do it like this in the /project/api/.htaccess
file (so as to restrict the directories affected):
# /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]
Note that you will need to clear any local caches since 301 (permanent) redirects are generally cached by default.
HOWEVER, I would avoid disabling DirectorySlash
as this could result in additional issues depending on your system. And using a non-descriptive index.php
file is not recommended anyway. Instead I would rethink your file structure a little and perhaps just remove the .php
extension from your requests.
For example, the file structure could be like the following instead:
📂project
┗ 📂api
┗ 📜engine.php
┗ 📜history.php
Your API requests would then be of the form /project/api/engine
(and /project/api/history
as opposed to /project/api/engine/history.php
).
In your /project/api/.htaccess
you just need some code to append the .php
extension via an internal rewrite. For example:
# /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]
Optionally, you could also block any direct requests to the .php
files themselves.