Reputation: 37
I have a website composed of PHP files, so I have the following configuration within my .htaccess file to hide the ".php" extension from my URLs:
.htaccess configuration
RewriteEngine on
RewriteCond %{THE_REQUEST} /([^.]+)\.php [NC]
RewriteRule ^ /%1 [NC,L,R]
Then as I was recently updating and debugging my my asynchronous javascript form-handler, I discovered that the fetch API would fail to pass any of the form data to the PHP horm-handler (despite calling the API) if I included the ".php" file extension in the URI, and only worked if I excluded the ".php" file extension.
Javascript with bugged fetch API:
const form= document.getElementById('form');
form.addEventListener('submit', (e) => {
e.preventDefault();
...
const data = new FormData(form);
postData();
async function postData() {
try {
const res = await fetch('form-handler.php', {
method: 'POST',
body: data,
})
} catch (err) {
}
}
});
Debugged fetch API:
const res = await fetch('form-handler', {
method: 'POST',
body: data,
})
So my question is as above: Does the configuration I put into my .htaccess file also affect my fetch API calls, resulting in the fact that I need to exclude the .php file extension in order for the fetch API to work properly? Thanks.
Upvotes: 0
Views: 39
Reputation: 45948
Yes, you need to request the canonical URL without the .php
extension. All your requests must be to the canonical URLs. In your scenario, the .php
extension should not be visible to the end user.
But the "redirect" rule you've posted is not sufficient by itself to allow extensionless URLs to work (you might be relying on MultiViews
- but this is not enabled by default on Apache). In fact, this "redirect" should not be required at all for your site to function (required only for SEO, if at all). If you are relying on this rule then you are linking to the wrong URLs.
UPDATE:
all my internal links include the .php extension, but they work just fine
This is a problem. Despite what it might look like at first, they don't work "just fine". Look closer.
If you have a link like this in your HTML:
<a href="foo.php">Foo Page</a>
The .php
extension is immediately accessible to the end user. They can view the HTML source and hover over the link to see the .php
extension in the status bar. When search engines crawl your site they are going to make requests for and crawl foo.php
.
When the user/search engine bot makes a request for foo.php
your rule in .htaccess
sends a 302 (temporary) redirect response back to the client/browser/bot with a Location
header instructing the user-agent of the new URL (without the .php
extension). The client/browser/bot then makes a 2nd (entirely new) HTTP request for the URL without the .php
extension. Your server then processes this request and sends back the (expected) response.
This additional/unnecessary redirect naturally results in 2 entries in your server's access log for every single page request (the first a 302, followed by the actual response eg, 200, 404, etc.)
The .php
should be completely invisible to the end-user/bot.
The reason why your API "POST" request fails completely is for one or two reasons:
Does your JavaScript API request follow "redirects"? APIs should be requesting the canonical URL, so they would not necessarily be expected to follow redirects at all. (Redirects are relatively slow.)
If you send back a 302 (or 301) redirect in response to a POST request then the user-agent/browser will often convert this to a GET request on the 2nd/redirected request, so all the POST data is lost. To get around this you can send back a 307 (or 308) instead that specifically instructs the user-agent to preserve the request method. However, as mentioned above, this "API" request should not need to be redirected in the first place. (And if the source of the API request does follow redirects, as mentioned in #1, then changing the HTTP status of the redirect is not going to help.)
The only reason to implement a redirect, "like" you have done, is to preserve SEO if you have changed an existing URL structure. And/or to direct users who have bookmarked the old URL with an extension. Otherwise, this redirect is not required. mod_rewrite does not, by itself, change URLs. To change URLs (eg. from foo.php
to foo
) you need to actually change the URLs in your application (as used in the HTML and JavaScript etc.). It is a common misconception that you can "change the URL" using .htaccess
. (.htaccess
is used to inernally rewrite a URL to the underlying file-path that handles the request.)
And to benefit SEO this redirect would need to be a 301 (permanent) redirect, not a 302 (temporary) redirect that you have here.
RewriteCond %{THE_REQUEST} /([^.]+)\.php [NC] RewriteRule ^ /%1 [NC,L,R]
This rule could also result in some invalid redirects since the regex in the condition is a bit vague. eg. Should requests for /file-does-not-exist.php
be redirected? And what about /foo/bar?baz.php
?
Extensionless URLs don't work by default. You can either:
Enable MultiViews
(part of mod_negotiation). This is disabled by default, but some shared hosts do enable this. This is unique to Apache and allows extensionless URLs to just "magically" work. However, unless you know what you are doing this can have some major caveats:
foo.php
and foo
are accessible and return the same content.foo.html
and foo.php
, which should your server respond with when requesting foo
?Use mod_rewrite. (Although you don't appear to be doing that here.)
Upvotes: 1