Is it possible to redirect all url paths to the root handler in App Engine in a nodejs app?
Asked Answered
G

2

0

I'm using App Engine to host a Nodejs SPA, I don't need routes so I would like to redirect all handlers to the root one. Example: redirect domain.tld/nsa-secrets to domain.tld

I have tried configuring a handler as the example in the documentation, but I always get the default not found Apache html.

Here is my app.yaml:

runtime: nodejs10
instance_class: F2

handlers:
- url: /
  static_files: dist/index.html
  upload: dist/index.html

- url: /
  static_dir: dist

- url: /.*
  secure: always
  redirect_http_response_code: 301
  script: auto

error_handlers:
- file: error.html

I see an error then shows in Error Reporting:

Error: Cannot find module '/srv/server.js'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:582:15)
    at Function.Module._load (internal/modules/cjs/loader.js:508:25)
    at Function.Module.runMain (internal/modules/cjs/loader.js:754:12)
    at startup (internal/bootstrap/node.js:283:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:622:3)

Shall I need to manually implement an url handler in server.js?

Thanks for the time and help.

Guillaume answered 24/5, 2019 at 1:2 Comment(0)
E
1

Would you try Firebase Hosting?

Firebase Hosting is better than App Engine to hosting a SPA .

See:

  • https://firebase.google.com/docs/hosting/use-cases

    Benefit from Firebase Hosting's unique optimization for serving single-page web apps and static websites. Delivery of static assets (HTML, CSS, JavaScript, fonts, etc.) is powered by our SSD backend storage and a global CDN with edge locations across all major locations in the world. You can even cache your dynamic content on the global CDN. All sites hosted by Firebase also get a free SSL certificate, so your content is always delivered securely.

  • https://firebase.google.com/docs/hosting/full-config#rewrites
Ellisellison answered 25/5, 2019 at 13:41 Comment(0)
K
0

Angular + Cloud Functions for Firebase + Firebase Hosting + NestJS approach.

  1. Rename index.html to index2.html. This is important to render your route path, otherwise you will have rendering working fine on all routes, excluding the root /.
  2. Update angular.json to have the following "index": "apps/myapp/src/index2.html", (Simply change index.html to index2.html). Note: path to the index.html might be different for you, I'm using Nx workspace.
  3. Add templatePath: join(BROWSER_DIR, 'index2.html'), to NestJS's ApplicationModule, most probably you name the file as app.module.ts in a server directory.

Like so:

@Module({
  imports: [
    AngularUniversalModule.forRoot({
      bundle: require('./path/to/server/main'), // Bundle is created dynamically during build process.
      liveReload: true,
      templatePath: join(BROWSER_DIR, 'index2.html'),
      viewsPath: BROWSER_DIR
    })
  ]
})
  1. Initialize Firebase Cloud Functions and Firebase Hosting, for how to set up this you can check https://hackernoon.com/deploying-angular-universal-v6-with-firebase-c86381ddd445 or https://blog.angularindepth.com/angular-5-universal-firebase-4c85a7d00862

  2. Edit your firebase.json.

It should look like that, or at least the hosting part.

{
  "hosting": {
    "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
    "public": "functions/path/to/browser",
    "rewrites": [
      {
        "function": "angularUniversalFunction",
        "source": "**"
      }
    ]
  }
} 
  1. In your main.ts you need to set up Cloud Functions on your server.

In a minimialistic case it would like something like that:

import * as admin from 'firebase-admin';
import * as functions from 'firebase-functions';

admin.initializeApp(); // Initialize Firebase SDK.
const expressApp: Express = express(); // Create Express instance.

// Create and init NestJS application based on Express instance.
(async () => {
  const nestApp = await NestFactory.create<NestExpressApplication>(
    ApplicationModule,
    new ExpressAdapter(expressApp)
  );
  nestApp.init();
})().catch(err => console.error(err));

// Firebase Cloud Function for Server Side Rendering (SSR).
exports.angularUniversalFunction = functions.https.onRequest(expressApp);

With this approach you don't have to care about routes on the NestJS side. You can set up everything on the Angular side, and that's all. Angular takes care for routing. As you probably noticed this is Server-Side Rendering (SSR), but redirection of all routes to index.html (or more precisely index2.html) can be done using NestJS + Cloud Functions for Firebase in conjuction. Plus you have a SSR "for free" :)

Projects to showcase:

1) Angular + Angular Universal (SSR) + Cloud Functions for Firebase: https://github.com/Ismaestro/angular8-example-app (missing NestJS).

2) Angular + NestJS: https://github.com/kamilmysliwiec/universal-nest (missing Cloud Functions for Firebase).

Kudos answered 14/8, 2019 at 11:7 Comment(2)
Unfortunately this is a no go for anyone outside the US, as Firebase functions only work with hosting region = USJealousy
@Jealousy I'm located outside US and it worked out. However, your hosting will be simply in the US, which theoretically can introduce some communication delay.Kudos

© 2022 - 2024 — McMap. All rights reserved.