Nodejs hapi single page

I have one application site (NodeJS) and I want to switch from Express to Hapi, what I usually do is static files and redirecting everything else to one page containing the angularjs application and the angular routing configuration.

// Express routing, first the static files app.use( express.static(__dirname + '/public') ); // Second the api routes app.get('/api', function(req, res){ res.send( {api: 'response' } ) }); // Finally everything else maps to the single page app: app.get('*', function(req, res){ res.sendfile('./public/html/controllers.index.html') }); 

In HapiJS, I don't know how to copy the same code (without using express.static middleware), because:

 Hapi = require('hapi'); var server = new Hapi.Server('localhost', 84); server.route({ method: 'GET', path: '/{p*}', handler: function (request, reply) { reply.file('public/html/index.html'); } }); 

In the above code, each request no matter what will be displayed on my only page ('public / html / index.html'), but if I do, then js, css, jpg and files will be displayed to the same file instead scripts, styles, and images (a request to "/images/bg.png" will load one page instead of an image file).

I know that if I set the path "/" to my only page and then "{p *}" to "{directory: {path: '/ public'}}, then I will have the behavior that I need but theres one catch if any user copies and pastes a specific url (say '/ account / login') and then press enter, this route will be displayed in HapiJS and the answer will be โ€œNot Found (404)โ€. angular routing will never be able to respond.

Does anyone know how to solve this?

The key part of the question:

  • Use only HapiJS (without special or other middleware).
  • Do not route each angular route (just go through everything else that is not redirected to the page yet, the angular page can handle routing)
+8
angularjs routing hapijs
source share
5 answers

Not sure if this will help you, but your starter code is a bit "weird" for Hapi.js. This is what I use to create a simple hapi.js SPA.

If you want to use specific URLs such as Account / Login, you must direct your path to this particular section. (path: '/ account / login')

The difference is that I point to the catalog as a whole, including. different files and you just respond to the index.html file. The listing parameter allows you to decide whether you want to display the directory structure or not in your URLs. The default value is false.

More information here: http://hapijs.com/tutorials/serving-files#directory-handler

 var Hapi = require('hapi'); var Path = require('path'); var server = new Hapi.Server(8080, 'localhost'); server.route({ method: 'GET', path: '/{path*}', handler: { directory: { path: './public', listing: false, index: true } } }); server.start(function(){ console.log('server started'); }); 
+7
source share

Inspired by inert documentation, I solved this by serving everything from a static directory. Then I added onPostHandler to return the index file whenever 404 is returned. Then the client router can send a redirect to the existing 404.html file in the static files directory.

 // 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(); }); 
+5
source share

This answer is not valid. Like @Al Jay said in a comment. Hapi has its own algorithm for sorting routes, please do not follow this answer.


Like expressJS, Hapi processes the route on order. Just specify the order of the routes by priority:

 server.route( { // Angular/API Route method: 'GET', path: '/api', handler: function (request, reply) { reply( {api: 'response' } ) } }); server.route({ // Other assets If you have method: 'GET', path: '/assets/{param*}', handler: { directory: { path: './assets', listing: false, index: true } }); server.route({ // Everything else method: 'GET', path: '/{p*}', handler: function (request, reply) { reply.file('public/html/index.html'); } }); 
+1
source share

I have had success with the inert, as described here . If you scroll down the page, you can find the Directory Handler section.

My solution looks like this:

 var Hapi = require('hapi'); var Path = require('path'); var server = new Hapi.Server(); server.connection({ host: 'localhost', port: 8001 }); server.register(require('inert'), (err) => { if (err) { throw err; } server.route({ method: 'GET', path: '/{param*}', handler: { directory: { path: 'public' } } }); server.start((err) => { if (err) { throw err; } console.log('Server running at:', server.info.uri); }); }); 
+1
source share

Make sure you have an inert plugin.

In your server.js server (or whatever you called it) configure the relative path for serving static files below

 const server = new Hapi.Server({ connections: { routes: { cors: true, files: { relativeTo: Path.join(__dirname, 'public') } }, router: { stripTrailingSlash: true } } }) 

then register a new route plugin for your route as shown below. This assumes that the entry index.html (for React or Angular) is inside a shared directory as above

 exports.register = (server, options, next) => { server.route([{ method: 'GET', path: '/{param*}', handler: { directory: { path: '.', redirectToSlash: true, listing: false, index: true } } }]) server.ext('onPostHandler', (req, res) => { const response = req.response if (response.isBoom && response.output.statusCode >= 404) { return res.file('index.html') } return res.continue() }) next() } exports.register.attributes = { name: 'static-route', version: '1.0.0' } 

Now, every time HapiJS throws a 404 error, the route is redirected to your React / Angular application, which can then process the route if it exists.

+1
source share

All Articles