我应该如何从 Express 中间件中调用异步函数?

问题描述 投票:0回答:1

我已经能够将此问题简化为一个单文件示例,该示例应该可以使用 Express 5.0.0-beta.1 轻松重现。

我正在编写一个 Express 中间件函数,它实现基本的 JWT 身份验证。逻辑非常简单:从

Authorization
标头中提取令牌(如果不存在/格式错误,则返回 401),然后将令牌插入到我们称为
validateToken
的内部函数中,该函数返回 Promise。 注意:我相信这是 Stack Overflow 上的一个独特问题,这个问题是关于从 在端点处理程序中进行异步调用,但我需要从 在中间件函数中进行异步调用。

我尝试通过以下方式实现这一点:

const express = require('express');
const app = express();

class HttpError {
    constructor(status, message) {
        this.status = status
        this.message = message
    }
}

// Auth middleware
const authMiddleware = (req, res, next) => {

        const token = req.header('Authorization');
        if (!token) {
            console.info("No JWT in request")
            return next(new HttpError(401, 'Unauthorized'))
        }
    
        const regex = /^Bearer (.+)$/;
        const jwt = regex.exec(token)[1];
    
        if (!jwt) {
            console.info("Malformed JWT")
            return next(new HttpError(401, 'Unauthorized'))
        }

        return validateToken({jwt: jwt, path: '/secured'})
            .then((response) => next())
            .catch(err => next(new HttpError(403, 'Forbidden')))   
}
app.use(authMiddleware)

// Endpoint definitions
app.get('/secured', (req, res) => {
    console.info('endpoint handler invoked')
    res.send('Valid token')
})

// Error handlers
function errorMiddleware(error, req, res, next) {
    console.info(`error middleware hit: ${JSON.stringify(error)}`)
    if (!error.status || error.status >= 500) {
        return res.status(error.status || 500).send();
    }
            
    res.status(error.status).json({ message: error.message });
}
app.use(errorMiddleware)

app.listen(8080);

当我发送不带

Authorization
标头的请求并且触发前两个
if
块之一(返回
next(new HttpError(...)
)时,应用程序立即向客户端发出 401 Unauthorized 响应。但是,当我发送带有标头中的令牌的请求时,应用程序会无限期地挂在中间件函数的最后 return validateToken(...) 行上。
我被告知 Express 5.x 会自动处理中间件函数中被拒绝的 Promise,但即使升级到 Express 5 后,应用程序在调用异步函数时仍然会无限期挂起 

validateToken

    

node.js express asynchronous
1个回答
0
投票
validateToken

函数有一些非常奇怪的行为 - 在验证令牌之前,它等待对 AWS 元数据服务的 HTTP 调用以获取有关系统的一些信息。我以为我的异步 Express 代码犯了一个错误,但实际上

对 AWS 的调用需要 75 秒才超时
,超时后,处理程序完全按照应有的方式运行。 这是一个 Express 服务器的单文件示例,它等待异步操作

在中间件中

,希望这对将来的人有所帮助: const express = require('express'); const app = express(); class HttpError { constructor(status, message) { this.status = status this.message = message } } // Auth middleware const authMiddleware = (req, res, next) => { const token = req.header('Authorization'); if (!token) { console.info("No JWT in request") return next(new HttpError(401, 'Unauthorized')) } const regex = /^Bearer (.+)$/; const jwt = regex.exec(token)[1]; if (!jwt) { console.info("Malformed JWT") return next(new HttpError(401, 'Unauthorized')) } // Assume that `validateToken` is a function returning a promise with either the token's claims or an error return this.validateToken({jwt: jwt, path: '/secured'}) .then((response) => next()) .catch(err => next(new HttpError(403, 'Forbidden'))) } // Invoke authMiddleware function for all endpoints that begin with '/secured' app.use('/secured', authMiddleware) // Endpoint definitions app.get('/secured', (req, res) => { res.send('Valid token') }) app.get('/unsecured', (req, res) => res.send('Unsecured endpoint')) // Error handlers function errorMiddleware(error, req, res, next) { console.debug(`Error caught by Express error handler: ${JSON.stringify(error)}`) if (!error.status || error.status >= 500) { return res.status(error.status || 500).send(); } res.status(error.status).json({ message: error.message }); } app.use(errorMiddleware) app.listen(8080);

© www.soinside.com 2019 - 2024. All rights reserved.