【问题标题】:HapiJS global path prefixHapiJS 全局路径前缀
【发布时间】:2015-03-08 09:49:20
【问题描述】:

我正在 HapiJS 上编写 API,并且想知道如何获取全局前缀。例如,所有请求都应发送至:

https://api.mysite.com/v0/...

所以我想将v0 配置为全局前缀。文档 (here) 似乎没有提到它——在 HapiJS 中有没有好的方法来做到这一点?

【问题讨论】:

    标签: node.js url-routing hapijs


    【解决方案1】:
    server.realm.modifiers.route.prefix = '/api/v2'
    await server.route(yourroutes);
    

    这应该可以正常工作,但是如果您希望能够从您的路由目录/文件Hapi Router 自动解析所有路由。你可以做这样的事情,这会节省你很多时间。

    await server.register({
        plugin: HapiRouter,
        options: {
            routes: "./src/routes/product-routes.js",
        },
    }, {
        routes: {
            prefix: "/api/v1"
        }
    });
    

    您的路线文件应该如下所示。

    export default [{
        method: "GET",
        path: "/products",
        options: {
            tags: ["api", "Products"],
            description: "Get All Products",
        },
        handler: () => {...}
    }]
    

    【讨论】:

      【解决方案2】:

      对于 Hapi 19、20 ...您可以在注册之前使用 ma​​p 路径简单地修改路线。

      // Example route
      const routes = [
          {
              method: 'GET',
              path: '/test',
              handler: function (request) {
                  return {
                      status: 'success'
                      };
                  }
          }
      ];
      
      // transform /test -> /api/test
      routes.map((r) => {
          r.path = `/api${r.path}`;
          return null;
      });
      
      
      // Register
      server.route([
          ...routes
      ]);
      

      【讨论】:

        【解决方案3】:

        这是我的实现方式

        我创建了一个辅助函数,它接受一个 Hapi.ServerRoute 数组,然后映射它并连接前缀,然后返回数组。

        sn-ps 在 Typescript 中,所以如果你使用 JavaScript,只需去掉类型

        // Helper function
        export function routerGroup (namespace: string, routes: Hapi.ServerRoute[]) {
          return routes.map(r => {
            r.path = namespace + r.path
            return r
          })
        }
        
        // Routes declarations
        
        export default routerGroup('/v1/api', [
            {
                method: 'POST',
                path: '/login',
                options: {
                    validate: {
                        payload: Joi.object({
                            email: Joi.string().required().email(),
                            password: Joi.string().required().min(8).max(30)
                        })
                    },
                    auth: false
                },
                handler: Authentication.adminLogin
            }
        ] as Hapi.ServerRoute[]
        )
        
        // Register routes to Hapi server
        server.route(
          [
            ...v1Routes,
            ...
          ]
        )
        

        【讨论】:

          【解决方案4】:

          我参加这个聚会迟到了,但它出现在搜索结果中。FWIW,我正在使用它,基于 AdrieanKhisbe’s answer。它允许设置多个全局前缀并使用子路由前缀(类似于 Django url 的布局方式)。这是一个包含多个 route.js 文件和 api 路由版本的示例(为清楚起见,路由处理程序已移出):

          /departments/routes.js

          const { getDepartments, getDepartmentById } = require('./handlers');
          
          module.exports = [
            { method: 'GET', path: '', handler: getDepartments },
            { method: 'GET', path: '/{id}', handler: getDepartmentById }
          ];
          

          /users/routes.js

          const { getUsersV1, getUserByIdV1, getUsersV2, getUserByIdV2 } = require('./handlers');
          
          const userRoutesV1 = [
            { method: 'GET', path: '', handler: getUsersV1 },
            { method: 'GET', path: '/{id}', handler: getUserByIdV1 }
          ];
          
          const userRoutesV2 = [
            { method: 'GET', path: '', handler: getUsersV2 },
            { method: 'GET', path: '/{id}', handler: getUserByIdV2 }
          ];
          
          module.exports = { userRoutesV1, userRoutesV2 };
          

          index.js

          const Hapi = require('@hapi/hapi');
          const departmentRoutes = require('./departments/routes');
          const { userRoutesV1, userRoutesV2 } = require('./users/routes');
          
          const init = async () => {
            const server = Hapi.server({
              port: 3000,
              host: 'localhost',
            });
          
            const allRoutes = [];
          
            const v1 = '/api/v1/';
            const v2 = '/api/v2/';
          
            const prefixer = (routeArray, apiPrefix, subRoutePrefix) => {
              routeArray.map(route => {
                route.path = `${apiPrefix}${subRoutePrefix}${route.path}`;
                allRoutes.push(route);
              });
            };
          
            prefixer(departmentRoutes, v1, 'departments');
            prefixer(userRoutesV1, v1, 'users');
            prefixer(userRoutesV2, v2, 'users');
          
            server.route(allRoutes);
          
            await server.start();
            console.log('Server running on %s', server.info.uri);
          };
          
          process.on('unhandledRejection', err => {
            console.log(err);
            process.exit(1);
          });
          
          init();
          

          【讨论】:

            【解决方案5】:

            看看hapi-auto-route。这个插件会自动从一个目录注册你的路由

            // Directory structure
            // 
            // node_modules/
            // routes/
            //  home.js
            // server.js
            // package.json
            
            // routes/home.js
            'use strict';
            
            module.exports = {
                method: 'GET',
                path: '/',
                handler: (request, h) => 'Hello';
            }
            
            // server.js
            'use strict';
            
            const Hapi = require('hapi');
            
            const server = Hapi.Server({
              port: 3000,
              host: 'localhost'
            });
            
            const init = async () => {
                await server.register(require('hapi-auto-route'));
                await server.start();
                console.log(`Server is running at: ${server.info.uri}`);
            };
            
            process.on('unhandledRejection', (error) => {
              console.log(error);
              process.exit();
            });
            
            init()

            并为其添加前缀:

            【讨论】:

              【解决方案6】:

              我能够让它适用于所有路线

              var server = new Hapi.Server()
              ...
              server.realm.modifiers.route.prefix = '/v0'
              server.route(...)
              

              【讨论】:

                【解决方案7】:

                Matt Harrisson's answerhapi 使用插件的方式。

                或者,如果您不想创建插件只是为了添加前缀,您可以手动,将前缀添加到所有路由。

                例如,我选择了这样的东西:

                  var PREFIX = '/v0';
                  var routes = [/* array with all your root */];
                
                  var prefixize = function (route) {  route.path = PREFIX + route.path;return route; }
                  server.route(routes.map(prefixize));
                

                好点是这样的事情你可以执行express-like安装。例如:

                 var prefixize = function (prefix, route) {  route.path = prefix + route.path;return route; }
                
                server.route(adminRoutes.map(prefixize.bind({}, "/admin"))); //currying.
                server.route(apiRoutes.map(prefixize.bind({}, "/api")));
                

                【讨论】:

                • 这是正确的答案,因为 Matt Harrisson 的答案不适用于大多数人都会拥有的多个插件。
                【解决方案8】:

                你总是可以像这样启动你的 index.js

                if (!global.PREFIX) {
                  global.PREFIX = '/v0';
                }
                

                通过这种方式,您可以在代码中的任何地方访问 PREFIX

                这就是您可以访问 PREFIX 的方式

                console.log(PREFIX);var name = PREFIX+ "_somename";

                【讨论】:

                  【解决方案9】:

                  如果您将 API 路由逻辑放在 Hapi plugin 中,例如 ./api.js

                  exports.register = function (server, options, next) {
                  
                      server.route({
                          method: 'GET',
                          path: '/hello',
                          handler: function (request, reply) {
                              reply('World');
                          }
                      });
                  
                      next();
                  
                  };
                  
                  exports.register.attributes = {
                      name: 'api',
                      version: '0.0.0'
                  };
                  

                  您向服务器注册插件并传递一个可选的路由前缀,该前缀将添加到插件内的所有路由之前:

                  var Hapi = require('hapi');
                  
                  var server = new Hapi.Server()
                  server.connection({
                      port: 3000
                  });
                  
                  server.register({
                      register: require('./api.js')
                  }, {
                      routes: {
                          prefix: '/v0'
                      }
                  },
                  function(err) {
                  
                      if (err) {
                          throw err;
                      }
                  
                      server.start(function() {
                          console.log('Server running on', server.info.uri)
                      })
                  
                  });
                  

                  您可以通过启动服务器并访问 http://localhost:3000/v0/hello 来验证它是否有效。

                  【讨论】:

                  • 我似乎无法使用这种方法。我可以使用server.realm.modifiers.route.prefix = '/v0' 直接设置它,但不能像您显示的那样通过嵌套选项进行设置。你确定你的方法有效吗?
                  • 是的,我刚刚用 Hapi 8 测试了它。不过,此前缀选项仅在注册单个插件时可用。因此,如果您要注册多个插件,它将无法正常工作。
                  • @MattHarrison 使用多插件免责声明更新您的答案可能是个好主意:)
                  • 这不适用于多个插件.. 80% 的 hapi 堆栈都有。
                  • @olive_tree 您现在可以为每个插件指定前缀选项hapijs.com/api#serverregisterplugins-options-callback。或者只是使用胶水
                  猜你喜欢
                  • 2013-01-26
                  • 2013-08-25
                  • 2018-06-15
                  • 2014-05-27
                  • 1970-01-01
                  • 2013-05-07
                  • 2014-03-31
                  • 2013-11-09
                  • 1970-01-01
                  相关资源
                  最近更新 更多