Express中app.use()内带括号调用的方法作为回调的运行原理问题
Express中间件工厂函数常见疑问解答
核心本质
node-expose-sspi的sso.auth是中间件工厂函数,本身不是符合Express规范的中间件,执行后才会返回可用的(req, res, next)格式中间件。
问题1:为什么传入时需要加()?
Express的app.use接收的参数必须是中间件函数、中间件数组、或者路由路径+中间件组合。普通场景下我们直接传入的函数本身就是中间件,所以不需要加()执行。
而sso.auth是用来生产中间件的工厂函数,只有加()调用后,才会返回符合要求的中间件函数,才能被app.use正常识别处理。如果不加()直接传sso.auth,相当于把工厂函数本身当成中间件传入,逻辑完全不符合预期。
问题2:加()调用的情况下为什么没有立即无参执行请求处理逻辑?
sso.auth()确实会立即执行,但它执行的逻辑是:接收你传入的配置参数(没传就用默认配置),生产并返回对应的中间件函数,不会直接处理请求。
真正的请求处理逻辑写在它返回的那个函数里,这个函数会被Express存起来,等到有请求进来的时候,才会被调用,同时传入当前请求的req、res、next三个参数,这时候才会执行sso校验、挂载req.sso等逻辑。
问题3:如何将这类方法封装到自定义回调函数中?
你之前写法出错的原因是:只调用了sso.auth()拿到了中间件函数,但没有执行这个中间件,也没有把当前请求的req、res、next传入这个中间件,自然不会给req挂载sso属性。
正确封装方式如下:
// 先调用工厂函数拿到可用的sso中间件,避免每次请求都重复生成 const ssoAuthMiddleware = sso.auth(); app.use(myCallback); function myCallback(req, res, next) { // 你可以在这里加自定义逻辑,比如路由判断、权限校验等 if (req.path.startsWith('/public')) { // 不需要sso校验的路径直接跳过 return next(); } // 把当前请求的req、res、next传入sso中间件执行 ssoAuthMiddleware(req, res, next); }
如果需要在sso校验完成后加自定义逻辑,也可以给next传入回调:
function myCallback(req, res, next) { ssoAuthMiddleware(req, res, (err) => { if (err) return next(err); // sso校验完成后执行自定义逻辑 console.log('当前登录用户:', req.sso?.user?.name); next(); }); }
内容的提问来源于stack exchange,提问作者Fusscreme
相关产品推荐
相关产品推荐

