web-dev-qa-db-fra.com

Comment stocker des itinéraires dans des fichiers séparés lors de l'utilisation de Hapi?

Tous les exemples Hapi (et similaires dans Express) montrent que les routes sont définies dans le fichier de départ:

var Hapi = require('hapi');

var server = new Hapi.Server();
server.connection({ port: 8000 });

server.route({
  method: 'GET',
  path: '/',
  handler: function (request, reply) {
    reply('Hello, world!');
  }
});

server.route({
  method: 'GET',
  path: '/{name}',
  handler: function (request, reply) {
    reply('Hello, ' + encodeURIComponent(request.params.name) + '!');
  }
});

server.start(function () {
  console.log('Server running at:', server.info.uri);
});

Cependant, il n'est pas difficile d'imaginer la taille de ce fichier lors de l'implémentation d'une application de production avec une tonne de routes différentes. Par conséquent, je voudrais décomposer les itinéraires, les regrouper et les stocker dans des fichiers séparés, comme UserRoutes.js, CartRoutes.js, puis les attacher dans le fichier principal (ajouter à l'objet serveur). Comment proposeriez-vous de séparer cela, puis d'ajouter?

47
Centurion

Vous pouvez créer un fichier séparé pour les itinéraires utilisateur (config/routes/user.js):

module.exports = [
    { method: 'GET', path: '/users', handler: function () {} },
    { method: 'GET', path: '/users/{id}', handler: function () {} }
];

De même avec le chariot. Créez ensuite un fichier d'index dans config/routes (config/routes/index.js):

var cart = require('./cart');
var user = require('./user');

module.exports = [].concat(cart, user);

Vous pouvez ensuite charger ce fichier d'index dans le fichier principal et appeler server.route():

var routes = require('./config/routes');

...

server.route(routes);

Alternativement, pour config/routes/index.js, Au lieu d'ajouter manuellement les fichiers de route (par exemple cart, user), vous pouvez les charger dynamiquement:

const fs = require('fs');

let routes = [];

fs.readdirSync(__dirname)
  .filter(file => file != 'index.js')
  .forEach(file => {
    routes = routes.concat(require(`./${file}`))
  });

module.exports = routes;
87
Gergo Erdosi

Vous devriez essayer le plugin Glue: https://github.com/hapijs/glue . Il vous permet de modulariser votre application. Vous pouvez placer vos itinéraires dans des sous-répertoires séparés, puis les inclure en tant que plugins Hapi.js. Vous pouvez également inclure d'autres plugins (Inert, Vision, Good) avec Glue ainsi que configurer votre application avec un objet manifeste (ou fichier json).

Exemple rapide:

server.js:

var Hapi = require('hapi');
var Glue = require('glue');

var manifest = {
    connections: [{
        port: 8080
    }],
    plugins: [
        { inert: [{}] },
        { vision: [{}] },
        { './index': null },
        {
            './api': [{
                routes: {
                    prefix: '/api/v1'
                }
            }]
        }
    ]
};


var options = {
    relativeTo: __dirname + '/modules'
};

Glue.compose(manifest, options, function (err, server) {
    server.start(function(err) {
        console.log('Server running at: %s://%s:%s', server.info.protocol, server.info.address, server.info.port);
    });
});

./ modules/index/index.js:

exports.register = function(server, options, next) {
    server.route({
        method: 'GET',
        path: '/',
        handler: require('./home')
    });
});

exports.register.attributes = {
    pkg: require('./package.json')
};

./ modules/index/package.json:

{
    "name": "IndexRoute",
    "version": "1.0.0"
}

./ modules/index/home.js:

exports.register = function(req, reply) {
    reply.view('home', { title: 'Awesome' });
});

Jetez un oeil à this merveilleux article de Dave Stevens pour plus de détails et d'exemples.

15
coquin

Vous pouvez utiliser require-hapiroutes pour faire une partie de l'organisation et du chargement pour vous. (Je suis l'auteur donc je suis un peu biaisé, je l'ai écrit pour me faciliter la vie dans la gestion des itinéraires)

Je suis un grand fan de require-directory et je voulais un moyen de gérer mes itinéraires tout aussi facilement. Cela vous permet de mélanger et de faire correspondre des routes dans vos modules et des modules dans des répertoires avec des routes.

Vous pouvez alors faire quelque chose comme ça ...

var routes = require('./routes');
server.route(routes.routes);

Ensuite, dans votre répertoire, vous pourriez avoir un fichier d'itinéraire comme ...

module.exports = [
{
  method : 'GET',
  path : '/route1',
  handler : routeHandler1,
  config : {
    description: 'my route description',
    notes: 'Important stuff to know about this route',
    tags : ['app']
  }
},
{
  method : 'GET',
  path : '/route2',
  handler : routeHandler2,
  config : {
    description: 'my route description',
    notes: 'Important stuff to know about this route',
    tags : ['app']
  }
}];

Ou, vous pouvez mélanger et assortir en attribuant à une propriété "routes" sur le module

module.exports.routes = [
{
  method : 'GET',
  path : '/route1',
  handler : routeHandler1,
  config : {
    description: 'my route description',
    notes: 'Important stuff to know about this route',
    tags : ['app']
  }
},
{
  method : 'GET',
  path : '/route2',
  handler : routeHandler2,
  config : {
    description: 'my route description',
    notes: 'Important stuff to know about this route',
    tags : ['app']
  }
}];

Toujours bien d'avoir des options. Il existe une documentation complète sur le site github ou npmjs pour cela.

6
Brian ONeil

ou vous pouvez utiliser un fichier d'index pour charger toutes les routes du répertoire

index.js

/**
 * Module dependencies.
 */
const fs = require('fs');
const path = require('path');
const basename  = path.basename(__filename);

const routes = fs.readdirSync(__dirname)
.filter((file) => {
    return (file.indexOf('.') !== 0) && (file !== basename);
})
.map((file) => {
    return require(path.join(__dirname, file));
});

module.exports = routes;

d'autres fichiers dans le même répertoire comme:

module.exports =  [
    {
        method: 'POST',
        path:  '/api/user',
        config: {

        }
    },
    {
        method: 'PUT',
        path:  'api/user/{userId}',
        config: {

        }
    }
];

et que dans votre racine/index

const Routes = require('./src/routes');
/**
* Add all the routes
*/
for (var route in Routes) {
    server.route(Routes[route]);
}
2
Whisher

Essayez hapi-auto-route plugin! Il est très simple à utiliser et autorise le préfixe dans le chemin de votre itinéraire.

0
sitrakay

Intéressant de voir autant de solutions différentes, en voici une autre.

Globbing à la rescousse

Pour mon dernier projet, j'ai opté pour la globalisation des fichiers avec un modèle de nom particulier, puis les exiger sur le serveur un par un.

Importer des routes après avoir créé l'objet server

// Construct and setup the server object.
// ...

// Require routes.
Glob.sync('**/*route*.js', { cwd: __dirname }).forEach(function (ith) {
    const route = require('./' + ith);
    if (route.hasOwnProperty('method') && route.hasOwnProperty('path')) {
        console.log('Adding route:', route.method, route.path);
        server.route(route);
    }
});

// Start the server.
// ...

Le motif glob **/*route*.js trouvera tous les fichiers dans et sous le répertoire de travail actuel spécifié avec un nom qui contient le mot route et se termine par le suffixe . js.

Structure des fichiers

Avec l'aide du globbing, nous avons un couplage lâche entre l'objet server et ses routes. Ajoutez simplement de nouveaux fichiers de route et ils seront inclus la prochaine fois que vous redémarrerez votre serveur.

J'aime structurer les fichiers de route en fonction de leur chemin et les nommer avec leur méthode HTTP, comme ceci:

server.js
routes/
    users/
        get-route.js
        patch-route.js
        put-route.js
    articles/
        get-route.js
        patch-route.js
        put-route.js

Exemple de fichier d'itinéraire routes/users/get-route.js

module.exports = {
    method: 'GET',
    path: '/users',
    config: {
        description: 'Fetch users',
        // ...
    },
    handler: function (request, reply) {
        // ...
    }
};

Dernières pensées

La globalisation et l'itération sur les fichiers ne sont pas un processus particulièrement rapide, donc une couche de mise en cache peut valoir la peine d'être étudiée dans les builds de production selon vos circonstances.

0
Fredric

Je sais que cela est déjà approuvé. J'ai déposé ma solution au cas où quelqu'un voudrait une solution rapide et nouveau pour Hapi.

J'ai également inclus du NPM pour que les Newbees puissent voir comment utiliser le server.register avec plusieurs plugins dans le cas (good + hapi-auto-route)

Installation de certains packages npm:

npm i -S hapi-auto-route

npm i -S good-console

npm i -S good


// server.js
'use strict';

const Hapi = require('hapi');
const Good = require('good');
const AutoRoute = require('hapi-auto-route');

const server = new Hapi.Server();

server.connection(
    {   
        routes: { cors: true }, 
        port: 3000, 
        Host: 'localhost',
        labels: ['web']
    }
);

server.register([{
    register: Good,
    options: {
        reporters: {
            console: [{
                module: 'good-squeeze',
                name: 'Squeeze',
                args: [{
                    response: '*',
                    log: '*'
                }]
            }, {
                module: 'good-console'
            }, 'stdout']
        }
    }
}, {
    register: AutoRoute,
    options: {}
}], (err) => {

     if (err) {
        throw err; // something bad happened loading the plugin
    }

    server.start((err) => {

        if (err) {
            throw err;
        }
        server.log('info', 'Server running at: ' + server.info.uri);
    });
});

Dans votre routes/user.js

module.exports = 
[   
     {  
        method: 'GET',
        path: '/',
        handler: (request, reply) => {
            reply('Hello, world!');
        } 
    },  
     {  
        method: 'GET',
        path: '/another',
        handler: (request, reply) => {
            reply('Hello, world again!');
        } 
    },
];

Exécutez maintenant: node server.js

À votre santé

0
Mr H