如何将Hapi.js插件应用于特定路由?

5
我有一个使用Hapi.js构建的服务器。我创建了一个插件来限制对某些本地网络IP地址的访问,就像这样:
exports.register = function (server, options, next) {
    server.ext({
        type: 'onRequest',
        method: function (request, reply) {
            console.log(request);
            if (
                request.info.remoteAddress.indexOf("192.") !== 0 &&
                request.info.remoteAddress.indexOf("127.") !== 0
            ) {
                return reply.view('error', {
                    error: "I DON'T LIKE YOU"
                });
            }
            return reply.continue();
        }
    });
    next();
};

exports.register.attributes = {
    pkg: { "name": "localOnly" }
};

我想将这个插件应用于仅“/pathA”,同时使“/pathB”和“/pathC”对所有用户可访问。因此,我尝试了以下操作:
const server = new Hapi.Server();
server.connection({ port: 8000 });
server.register(require('vision'), err => {
    if (err) throw err;
    server.views(/* removed for brevity */);
    server.route({ method: 'GET', path: '/pathB', handler: handlerB });
    server.route({ method: 'GET', path: '/pathC', handler: handlerC });
    server.register(require('./plugins/localOnly.js'), err => {
        if (err) throw err;
        server.route({ method: 'GET', path: '/pathA', handler: handlerA });
        server.start(/* removed for brevity */);
    });
});

但是,似乎我的插件拦截了所有连接。有人能告诉我我做错了什么吗?如果您建议我进行完全重构也没关系。我现在只是在计划应用程序,并想尝试一下 Hapi.js。

2个回答

13

需要使用插件吗?如果不需要,您可以使用路由级别的扩展点。例如:

路由级别扩展

const restrict = function (request, reply) {

    if (/^(192|127)/.test(request.info.remoteAddress)) {
        return reply('Blocked');
    }

    return reply.continue();
};

server.route({
    config: {
        ext: {
            onPreAuth: { method: restrict }
        }
    },
    method: 'GET',
    path: '/pathA',
    handler: function (request, reply) {

        reply('Hello!');
    }
});

使用插件的另一种方法:

使用sandbox: plugin在插件内添加路由

const plugin = function (server, options, next) {

    const restrict = function (request, reply) {

        if (/^(192|127)/.test(request.info.remoteAddress)) {
            return reply('Blocked');
        }

        return reply.continue();
    };

    // only applies to route in this plugin

    server.ext('onPreAuth', restrict, { sandbox: 'plugin' }); 

    server.route({
        method: 'GET',
        path: '/pathA',
        handler: function (request, reply) {

            reply('Hello!');
        }
    });

    return next();
};

把它作为一个“路由级扩展”非常适合我!感谢您的帮助和时间!很遗憾我不能点赞你,显然还不允许。 - nopotato

5

对于较新版本的Hapi(当前为v17),您需要将路由选项作为route.options.plugins['myPluginName']传递,例如:

{
  method: 'GET',
  path: '/home',
  options: {
    plugins: {
       myPluginName: true
    }
  }
}

这可以在插件中的onPreAuth或更晚的钩子中通过ext获取。例如:
register: async (server, options) => {
  server.ext({
    type: 'onPreAuth',
    method: async (request, h) => {
      // Exit early if the route is not configured for this route
      if (!request.route.settings.plugins.myPluginName) { return h.continue }
      // ... runs before the route handler ...
    }
  })
}

请注意,钩子必须晚于 Hapi 生命周期中的 onRequest,因为此时还没有加载路由。如果您想要访问身份验证信息,则必须使用 onPostAuth。
该方法具有路由和插件之间松耦合的优点。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接