Hapi: Catch all route to hook node with Angular

Created on 30 Apr 2013  路  10Comments  路  Source: hapijs/hapi

Hi.
I am trying to connect an Angular app to a hapi node server.
My routes in hapi are of two kind:

  1. /api/xxxxx - for the api routes that I use to respond to the client
  2. anything else should just reply with the index.html page, in order for angular to take care of the front end routing.

I have created the following route which I was hoping that will render index html for all the routes (including the localhost ( / ) ).

var indexRoute = {
    method: 'GET',
    path: '/{path*}',
    config: handler: {
        directory: { path: './app', listing: false, index: true }
    }
};

It seems to work fine when I have the html5 mode of Angular disabled (so I am using normal hashbang URLs). When I turn this on, any route apart from the localhost returns with a 404, instead of rendering the index.html page. It seems that any URL (eg. localhost:8080/testUrl ) is not being handled by the indexRoute specified above.

Any ideas on how to solve this issue? Am I doing something wrong in the route?

Thank you very much and keep up the great work.

support

Most helpful comment

After reading the inert documentation, I solved this single-page app "issue" as follows:

// Static Assets
server.route({
  method: 'GET',
  path: '/{param*}',
  handler: {
    directory: {
      path: ['app/static'],
      listing: false,
      index: ['index.html']
    }
  }
});

// return index.html for everything else
server.ext('onPostHandler', (request, reply) => {
  console.log('WORD');
  const response = request.response;
  if (response.isBoom && response.output.statusCode === 404) {
    return reply.file('app/static/index.html');
  }
  return reply.continue();
});

I hope this helps somebody along the way.

All 10 comments

Is there a CORS issue? Are all the other methods GET?

Thank you for the answer. All the other methods are GET.
There does not seem to be a CORS issue. I get the standard hapi route not found 404 page.
To provide some more details:

  1. when I have html 5 links off and i go to : localhost:8080/#/a-non-existsing-url, hapi routes this correctly to index and then angular routing kicks in.
  2. when i have html 5 links on and i go to : localhost:8080/a-non-existing-url, hapi throws a 404 page. I was hoping that it would redirect me to index but it does not.
  3. with html 5 links on if I create a link in index page with href: /an-existing-url, (this route is defined in angular and not in hapi), when i click the link i am taken in the correct page. When i then refresh the page hapi throws a 404 page to me.
    Hope this makes some sense. Let me know if you need more details.
    Thank you very much.

Have you tried to serve the file instead of the directory?
I have a Backbone app, but it should be fairly similar:

{
    method: 'GET',
    path: '/{path*}',
    config: {
        auth: false
    },
    handler: {
       file: './app/index.htmll'
   }
}

I'm serving the assets/content of public on a different route.

Also, take a look at the files options of the server, particularly relativeTo to check that you are serving the directory you think you're serving (I had a little trouble with that).

Hope that helps.

Try @MathieuLoutre suggestion using the file handler to as the catch all, and define a more specific route for the api calls.

Hi. Thanks for the advice.
However, if you try to serve a static file and you have a parameter in your path then hapi server throws an error.
"Error: Route path with static file path cannot contain a parameter"
And I do not think it is possible to create a catch all handler without a parameter.

Oh, yes, I do remember seeing that at some point.
I made a workaround, not sure if it's good practice or not, but you can try to define something like:

exports.getWebApp = function (request) {
  return './app/index.html';
};

and use it like so:

{
    method: 'GET',
    path: '/{path*}',
    config: {
        auth: false
    },
    handler: {
       file: exports.getWebApp
   }
}

This is working for me.

Fixed in 1.1.0

Fatal error: Hapi ["/www/server.js"] -  Error: New route /{path*} conflicts with existing /{path*}

What does it mean?

That you have two catch alls

After reading the inert documentation, I solved this single-page app "issue" as follows:

// Static Assets
server.route({
  method: 'GET',
  path: '/{param*}',
  handler: {
    directory: {
      path: ['app/static'],
      listing: false,
      index: ['index.html']
    }
  }
});

// return index.html for everything else
server.ext('onPostHandler', (request, reply) => {
  console.log('WORD');
  const response = request.response;
  if (response.isBoom && response.output.statusCode === 404) {
    return reply.file('app/static/index.html');
  }
  return reply.continue();
});

I hope this helps somebody along the way.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

DrMabuse23 picture DrMabuse23  路  5Comments

leore picture leore  路  4Comments

kevinsimper picture kevinsimper  路  4Comments

hovmand picture hovmand  路  3Comments

jney picture jney  路  4Comments