4

I have a Firebase hosted single page app.

I also have 3 Firebase functions (contact, plans, features) that the app and external sources make requests of.

My app has a custom domain, which I'd like to access my functions via.

This is my current firebase.json config

{
  "hosting": {
    "public": "www",
    "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]
  }
}

So currently all traffic goes to my app and routing is handled via my SPA. Access to my functions currently has to be done via the cloudfunctions.net URL which isn't ideal.

How can I add URL rewrite entries to this config so that my functions are accessible via my custom domain and my single page app handles the rest of the routes?

I have tried the following for the features endpoint:

"rewrites": [
  {
    "source": "/features/**",
    "function": "features"
  },
  {
    "source": "!/features/**",
    "destination": "/index.html"
  }
]

Where in my functions index.js I have:

...
exports.plans = functions.https.onRequest(plansApi);
exports.features = functions.https.onRequest(featuresApi);
exports.contact = functions.https.onRequest(contactApi);

But I receive 404 Cannot GET /features/123 as the response?

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
Greg
  • 31,180
  • 18
  • 65
  • 85

1 Answers1

8

A few things:

  1. Make sure that your featuresApi handler is matching for the full URL path (e.g. /features/123 not /123). Firebase Hosting forwards the full path to the function, not just the ** part.
  2. Rewrites are resolved in order, so there's no need to do !/features/** for your second rewrite source. ** should be fine since if it matches /features/** it will already match the first rewrite and resolve to the function.

Based on the error message, it seems likely that (1) is the culprit here.

Michael Bleigh
  • 25,334
  • 2
  • 79
  • 85
  • Brilliant, it was #1, is this documented and I just missed it? – Greg Feb 21 '19 at 09:24
  • Thanks Michael, I have the same issue and custom domain started working once I've added full URL path in each function, as you described in p-1. Is there any way to workaround, or do you have any suggestions to keep old URLs at *.cloudfunctions.net working for backwards compatibility ? I've added a gist with my sample code https://gist.github.com/rilian/dbc3ed86cf6b1365e1bdd4c2db469048 – rilian May 22 '19 at 20:52
  • Like if you have an Express app... Your POST-request is maybe: `/api/user/:task` and your Express app is defined in the variable `appAPIUser` and exported like so: `exports.appAPIUser = functions.https.onRequest(appAPIUser);` you should have a rewrite rule for hosting named like this (to include the correct parameters): `{ "source": "/api/user/**", "function": "appAPIUser" }`. – ravo10 Dec 12 '19 at 16:27
  • And on server side if you are using *cookie-session* (NPM) you can do something like: `req.sessionOptions.domain = req.hostname === 'us-central1-{{project-name}}.cloudfunctions.net' ? '{{project-name}}.web.app' : req.hostname;` and `req.sessionOptions.secure = req.secure`. Works good for me. – ravo10 Dec 12 '19 at 23:55