Paeon
Paeon

Reputation: 37

Does my .htaccess configuration also affect my internal fetch API calls?

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

Answers (1)

MrWhite
MrWhite

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:

Changing URLs

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.

API "POST" requests...

The reason why your API "POST" request fails completely is for one or two reasons:

  1. 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.)

  2. 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.)


Redirect to remove the file extension

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?

How do extensionless URLs work on Apache?

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:

    1. This enables extensionless URLs on literally everything (including images and other static assets, ...) and the additional overhead that this involves.
    2. You potentially have a duplicate content issue (on "everything") since both foo.php and foo are accessible and return the same content.
    3. If you have both foo.html and foo.php, which should your server respond with when requesting foo?
    4. Conflicts with mod_rewrite. (If you are doing any other URL rewriting then you should nearly always disable MultiViews - in fact this is a very common cause of error.)
  • Use mod_rewrite. (Although you don't appear to be doing that here.)

Upvotes: 1

Related Questions