Hapi路由生产环境返回404但本地正常,求排查方案
问题根源分析
你的代码存在几个关键问题,直接导致生产环境下非/healthcheck路由无法正常注册:
未声明变量触发严格模式报错
在/route/service1和/route/service2的handler中,payload和response变量未用const或let声明。生产环境通常默认启用JavaScript严格模式,未声明变量会抛出ReferenceError,导致这两个路由的注册逻辑直接失败,最终这些路由不存在,请求时返回404。而本地环境可能未启用严格模式,所以能正常运行。对象字面量语法错误(隐性问题)
/healthcheck路由的响应对象写法有误:{"message", "Server is UP and running"}正确的键值对应使用冒号分隔,而非逗号:
{"message": "Server is UP and running"}这个语法错误在部分宽松模式下可能被忽略,但严格模式下会直接报错,你提到/healthcheck能正常返回,大概率是本地环境的容错机制或代码输入时的笔误。
路由注册时序风险
你将部分路由放在server.start()之后注册,虽然Hapi支持启动后动态添加路由,但异步操作的时序在生产环境(如容器化部署、进程管理工具)中可能导致路由注册不及时或失败。
修复步骤
补全变量声明
修改两个服务路由的handler代码,为变量添加声明:handler: async (request, h) => { logger.log(["info", "stdout"], "Request received for route/service1"); const payload = await customFunction1(request.payload); const response = h.response(payload); response.code(200); return response; }/route/service2做同样修改。修正对象字面量语法
修复/healthcheck的响应对象:const response = h.response({"message": "Server is UP and running"});统一路由注册时机
将所有路由注册逻辑放在server.start()之前,彻底避免时序问题:const Hapi = require('hapi'); const server = new Hapi.Server({ port: 3000 }); // 一次性注册所有路由 server.route([ { method: "GET", path: "/healthcheck", handler: async (request, h) => { logger.log(["info", "stdout"], "Checking health"); const response = h.response({"message": "Server is UP and running"}); response.code(200); return response; } }, { method: "POST", path: "/route/service1", handler: async (request, h) => { logger.log(["info", "stdout"], "Request received for route/service1"); const payload = await customFunction1(request.payload); const response = h.response(payload); response.code(200); return response; } }, { method: "POST", path: "/route/service2", handler: async (request, h) => { logger.log(["info", "stdout"], "Request received for route/service2"); const payload = await customFunction2(request.payload); const response = h.response(payload); response.code(200); return response; } } ]); const init = async () => { try { await server.start(); logger.log(['info'], 'Server successfully started'); } catch (err) { logger.log(["error"], err); } }; init();检查生产环境日志
部署后查看生产环境的应用日志,确认是否还有其他报错(如customFunction1/customFunction2的依赖缺失问题),确保所有依赖在生产环境已正确安装。
内容的提问来源于stack exchange,提问作者Shamanth

