Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Request URLs are prefixed with the function "path" #1862

Closed
vmasek opened this issue Dec 12, 2019 · 8 comments · Fixed by #2984
Closed

Request URLs are prefixed with the function "path" #1862

vmasek opened this issue Dec 12, 2019 · 8 comments · Fixed by #2984
Assignees

Comments

@vmasek
Copy link

vmasek commented Dec 12, 2019

[REQUIRED] Environment info

firebase-tools: 7.9.0

Platform: Linux (Fedora 29)

[REQUIRED] Test case

Request URLs are used in the SSR (angular-universal) for navigation it seems that there is a breaking change in how they are handled by function emulator.

The last version I verified that doesn't have this issue is [email protected].
From what I identified the problem seems to be related to request URLs. If I log the values I see

app.get('*', (req: express.Request, res: express.Response) => {

  
  console.log(req.url, req.baseUrl, req.originalUrl);
  //  '/en/contact' '/web/us-central1/ssr' '/web/us-central1/ssr/en/contact'

  res.render('web-index', { req, res });
});

But in case of the older versions of firebase-tools let's say the version 6.8.0, output for the same code will be '/en/contact', '', '/en/contact'.

[REQUIRED] Steps to reproduce

Create a firebase function with minimal express setup and log the request object.

[REQUIRED] Expected behavior

URLs probably shouldn't be prefixed by the function base.

As a quick fix, I'm using replacing the prefix with request.baseUrl as a base should represent the prefix, but I'm not sure if it is the case in every possible scenario.

app.get('*', (req: express.Request, res: express.Response) => {

  req.originalUrl = req.originalUrl.replace(req.baseUrl, '');

  res.render('web-index', { req, res });

});

Another fix that may be a nicer solution is to explicitly set the url string.
res.render('web-index', { req, res, url: req.url });

[REQUIRED] Actual behavior

URLs are prefixed by the function base. Router inside the universal rendering doesn't recognize the routes correctly and renders the default page.

As already mentioned in #1279 it seems like a breaking change that should be eighter corrected or documented.

@fotoflo
Copy link

fotoflo commented Dec 8, 2020

A year later... is there any fix for this?

@vmasek
Copy link
Author

vmasek commented Dec 8, 2020

It seems like the workaround is now the preferred way to do this, as behaviour has changed and the functions have adjusted accordingly.

In my Angular SSR function, I provide the req.baseUrl as url and as the value of the APP_BASE_HREF

    res.render(indexHtml, {
      req,
      res,
      url: req.url,
      providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }],
    });

@samtstern
Copy link
Contributor

samtstern commented Dec 30, 2020

Ok I finally got around to taking another look at this one. Here's the function I wrote to reproduce:

const functions = require('firebase-functions');
const express = require('express');

const app = express();

app.get('*', (req, res) => {
  console.log();
  res.json({
    url: req.url, 
    baseUrl: req.baseUrl, 
    originalUrl: req.originalUrl
  })
});

exports.app = functions.https.onRequest(app);

In Emulator

$ http http://localhost:5001/ota-fir-dumpster/us-central1/app
HTTP/1.1 200 OK
connection: keep-alive
content-length: 107
content-type: application/json; charset=utf-8
date: Wed, 30 Dec 2020 12:38:10 GMT
etag: W/"6b-SnHfCzo9jWjTQGgDAwDu81tuOmE"
x-powered-by: Express

{
    "baseUrl": "/ota-fir-dumpster/us-central1/app",
    "originalUrl": "/ota-fir-dumpster/us-central1/app",
    "url": "/"
}
$ http http://localhost:5001/ota-fir-dumpster/us-central1/app/path/foo
HTTP/1.1 200 OK
connection: keep-alive
content-length: 124
content-type: application/json; charset=utf-8
date: Wed, 30 Dec 2020 12:38:16 GMT
etag: W/"7c-lwuBVeZMy6349B2FVhCt3+PGptU"
x-powered-by: Express

{
    "baseUrl": "/ota-fir-dumpster/us-central1/app",
    "originalUrl": "/ota-fir-dumpster/us-central1/app/path/foo",
    "url": "/path/foo"
}

In Production

$ http https://us-central1-ota-fir-dumpster.cloudfunctions.net/app
HTTP/1.1 200 OK
Alt-Svc: h3-29=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
Content-Length: 42
Content-Type: application/json; charset=utf-8
Date: Wed, 30 Dec 2020 12:40:03 GMT
Etag: W/"2a-2r6K6VdplGUiLl7XTpwje2YJ12g"
Function-Execution-Id: gxhndtuf9dlb
Server: Google Frontend
X-Cloud-Trace-Context: 5e85c00da8a0563a1076de38ecb54714;o=1
X-Powered-By: Express

{
    "baseUrl": "",
    "originalUrl": "/",
    "url": "/"
}
$ http https://us-central1-ota-fir-dumpster.cloudfunctions.net/app/path/foo
HTTP/1.1 200 OK
Alt-Svc: h3-29=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
Content-Length: 58
Content-Type: application/json; charset=utf-8
Date: Wed, 30 Dec 2020 12:40:09 GMT
Etag: W/"3a-TJpl1HpUobjuBCL03i7kbgn4ABk"
Function-Execution-Id: gxhndyw5iapw
Server: Google Frontend
X-Cloud-Trace-Context: 89a464a3ad411803131091be405c84f5
X-Powered-By: Express

{
    "baseUrl": "",
    "originalUrl": "/path/foo",
    "url": "/path/foo"
}

So it looks like url is correct but baseUrl and originalUrl both contain an unnecessary prefix of /ota-fir-dumpster/us-central1/app ... I'll look at how to remove that now.

@erikstorli
Copy link

erikstorli commented Jan 15, 2021

I've never had this problem with previous versions of firebase-cli, but after I updated firebase-cli to 9.2.0 I'm having this issue with the routes in my project. I copied your function above that you used to reproduce the issue.

Emulator returns:

{
  "url": "/project-id/europe-west1/app/foo/bar/path",
  "baseUrl": "",
  "originalUrl": "/project-id/europe-west1/app/foo/bar/path"
}

Production returns:

{
  "url": "/foo/bar/path",
  "baseUrl": "",
  "originalUrl": "/foo/bar/path"
}

Is this intended behavior? What am I misunderstanding here?

Reverting back to 9.1.0 makes the emulator return this:

{
  "url": "/foo/bar/path",
  "baseUrl": "/project-id/europe-west1/app",
  "originalUrl": "/project-id/europe-west1/app/foo/bar/path"
}

@samtstern
Copy link
Contributor

@erikstorli v9.2.0 introduced a new but with Functions in regions other than us-central1. It's fixed here and will be included in the next release:
#3033

@charles-allen
Copy link

charles-allen commented Feb 10, 2021

So it looks like url is correct but baseUrl and originalUrl both contain an unnecessary prefix of /ota-fir-dumpster/us-central1/app ... I'll look at how to remove that now.

Hi @samtstern - I don't understand this logic. In what sense is the base part of the URL unnecessary? How can I make a base relative href or src that works on the emulator if the baseUrl is set to nothing?

Edit: I guess baseUrl is not the correct solution for my problem; probably I need a ROOT_URL env variable?

@samtstern
Copy link
Contributor

@charles-allen I can totally see your use cases but our goal here is in this repo is simple: create emulators which locally match the behavior of Google Cloud Functions in production.

I can't offer any insight as to why GCF paths are the way they are, that sort of decision is a few years old and was made before these emulators existed! Changing it would be really disruptive so I think we'll have to live with the current behavior.

This was referenced Mar 9, 2021
@WikipediaBrown
Copy link

This is a bug and it's probably the most frustrating bug that exists on GCP. Worse, no matter who you talk to at Google, everyone acts like they don't understand why it's a problem. Like, you make an emulator that is basically useless for its most important use case. It's referenced so often and half way responded to by so many engineers there that it really seems like it will never be fixed. It truly makes me hate building on GCP.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants