skip to Main Content

I am using Firebase Hosting with cleanUrls.

Firebase Hosting also allows to enforce trailing slashes in all URLs with:

"hosting": {
  "trailingSlash": true
}

This will force a 301 redirect if the user requests a page without using a trailing slash. However, I’d like to enforce this redirect only for directories (i.e.: for serving index.html files).

According the documentation, you can leave trailingSlash as undefined. This will:

  • Serve /foo/bar/page with a 200 (/foo/bar/page.html)
  • Serve /foo/bar/ with a 200 (/foo/bar/index.html)
  • Serve /foo/bar with a 200 (/foo/bar/index.html)

The last part is unexpected, since I’d like to enforce trailing slashes for directories.

How can I enforce a 301 redirection for all directories to enforce a trailing slash only for them? In example:

  • Serve /foo/bar/page with a 200 (/foo/bar/page.html)
  • Serve /foo/bar/ with a 200 (/foo/bar/index.html)
  • Redirect /foo/bar with a 301 to /foo/bar/

Note there can be many directories so a solution that avoids writing a separate rule for each one is much preferred for maintainability.

Having /foo/bar return a 404 would be okay too, but 301 is preferred.

2

Answers


  1. Since Firebase Hosting’s configuration does not automatically differentiate between files and directories in the way traditional servers might, you could try and manually specify redirect rules for your known directory paths.

    But:

    • each directory would need a redirect rule. For projects with many directories, this can become cumbersome.
    • as commented, this does not work: the redirect rule for adding a trailing slash is too general or does not correctly discriminate between files and directories, causing Firebase Hosting to repeatedly attempt to redirect to the same path, adding a slash each time, … which results in a loop.

    Note there can be many directories so a solution that avoids writing a separate rule for each one is much preferred for maintainability.

    Then (and this is not tested) you would need to use Cloud Functions for Firebase or Firebase Hosting’s integration with Cloud Run to programmatically handle requests. That allows you to implement logic that checks if a requested path corresponds to a directory and enforce a trailing slash through redirection.

    Using a Cloud Function, that function intercepts HTTP requests, checks if the request URL corresponds to a directory (by checking if it maps to an index.html file in your public directory), and redirects to the same URL with a trailing slash if so.
    A pseudo-code example would be:

    const functions = require('firebase-functions');
    const path = require('path');
    const os = require('os');
    const fs = require('fs-extra');
    
    exports.addTrailingSlash = functions.https.onRequest(async (req, res) => {
      // Extract the path from the request URL
      const urlPath = req.path;
    
      // Construct the file system path to where the file would be located
      const filePath = path.join(os.tmpdir(), 'public', urlPath);
    
      // Check if an index.html exists for this path
      if (await fs.pathExists(path.join(filePath, 'index.html'))) {
        // Directory exists, redirect to path with trailing slash
        res.redirect(301, `${urlPath}/`);
      } else {
        // Not a directory or no index.html, handle normally
        // That might involve serving the file directly, showing a 404, etc.
      }
    });
    

    Route requests through this Cloud Function will use the rewrites feature in your firebase.json, allowing the function to process and redirect directory requests accordingly.
    Your firebase.json would need a rewrite rule to direct traffic to this function for handling:

    {
      "hosting": {
        "rewrites": [
          {
            "source": "**",
            "function": "addTrailingSlash"
          }
        ],
        // Other configurations
      }
    }
    

    But: routing all requests through a Cloud Function could introduce latency: do check the potential performance impact.
    And implementing logic with Cloud Functions or Cloud Run adds complexity to your project and may incur costs based on your usage, so you might have to do some Cloud FinOps.

    Login or Signup to reply.
  2. This can be done using firebase redirects and the fact you can use a regex in the firebase.json file:

    "redirects": [
          {
            "source": "**/:path" //Here a path matcher and a wildcard selector are used,
            "destination": "/:path/",
            "type": 301
          }
        ]
    

    This works assuming that all files end in an extension and folders don’t so try to keep it that way.

    Docs refrence

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search