首页 > 解决方案 > 为什么要在我的代码中表示“无法在将标头发送到客户端后设置标头”?

问题描述

我正在 Express 中创建某种登录请求/响应。当用户提供有效的用户名和密码时,服务器将返回有效的授权码。

这是代码。

export const getAuthKey = async (req, res, next) => {
    // Query parameter : :username, :hash(SHA256 encoded pasword)
    // Return : { authKey: authKey }
    if (req.query.username === undefined) { res.status(400).send('`username` query paramter missing.'); }
    if (req.query.hash === undefined) { res.status(400).send('`hash` query paramter missing.'); }
    getConnection()
        .then(conn => new Promise((resolve, reject) => {
            const escapeUserName = conn.escape(req.query.username);
            const escapeSHA256 = conn.escape(req.query.hash);
            return conn.query(`SELECT HEX(AuthorizationKey) AS authKey FROM UserInfo WHERE UserName = ${escapeUserName} AND UserPassword = UNHEX(${escapeSHA256});`)
                .then(result => resolve(result))
                .catch(err => reject(err))
                .finally(() => { conn.end(); });
        }))
        .then(auth => {
            if (auth.length < 1) { res.status(401).send('No such user found'); }
            else { 
                log(`User ${req.query.username} requests valid authorization.`, `AUTH`)
                res.json(auth[0]); 
            }
        })
        .catch(err => {
            log('Unable to get authKey', 'AUTH', 'ERROR', err);
            res.status(500).send(`Unable to logging-in`);
        });
}

步骤很简单,

1.用户用参数usernamehash(密码)1-1发送请求。如果参数不满足,则返回状态 400。 2. 检查数据库,查找用户是否有效,如果是,则返回其授权码。3-2 如果出现意外错误,返回状态 500。

此代码有效。但我总是看到 (node:11580) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

我想我想念一些关于http请求的东西。你能告诉我有什么问题吗?您还可以为我提供这种过程的代码模式吗?

ps请忽略函数定义上的异步。

标签: node.jsexpresshttprequest

解决方案


您询问的有关“将标头发送到客户端后无法设置标头”的特定错误是由于尝试向同一请求发送第二个响应而引起的。因此,通过代码的流程通常存在问题,导致它执行多个可以发送响应的代码路径。

在这两个语句上,您需要添加一个return语句,以便在您发送响应后代码不会继续在您的函数中执行:

if (req.query.username === undefined) { res.status(400).send('`username` query paramter missing.'); }
if (req.query.hash === undefined) { res.status(400).send('`hash` query paramter missing.'); }

即使您调用res.send()了 ,正常的 Javascript 流控制仍然适用,并且您的函数的其余部分将继续执行,导致您尝试发送另一个响应,这是“标头已发送”警告的来源。

因此,为这些语句中的每一个添加一个 return 以if在发送响应后停止该函数的进一步执行。

if (req.query.username === undefined) { 
    res.status(400).send('`username` query parameter missing.'); 
    return;
}
if (req.query.hash === undefined) { 
    res.status(400).send('`hash` query parameter missing.'); 
    return;
}

我还建议您稍微修改这些 if 语句以包含更多条件,例如空字符串:

if (!req.query.username) { 
    res.status(400).send('`username` query parameter missing.'); 
    return;
}
if (!req.query.hash) { 
    res.status(400).send('`hash` query parameter missing.'); 
    return;
}

仅供参考,还修复了“参数”的拼写。


推荐阅读