Node Express 认为我多次发送响应?

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

所以我正在尝试对快速中间件进行编程,并且我对每个

res.json()
res.send()
使用 return 语句,但我仍然收到错误:


Error [ERR_HTTP_HEADERS_SENT]: Cannot remove headers after they are sent to the client

我的 Express 中间件运行对象,但在 Express 服务器开始侦听之前,它们会被转换为其原始函数。

代码:


// first contact for all routes
    _app.all("*", (req, res, next) => {
        if(next == null || next == undefined) return res.json(null);
        // Has user logged in?
        info("Connection from: ", req.header("x-forwarded-for") || req.socket.remoteAddress);
        if (!hauth(req)) {
            // they havent
            res.locals.authed = false;
            if (req.route.path == NEW_AUTH_ROUTE) {
                // get user credentials, validate, and create new session for user.
                const auth = newauth(req);
                // returns new auth key if user credentials are valid, 
                // otherwise an error prompting the user to login again.
                return res.json(auth == null ? ServerResponse.authFail : prepareResponsePayload(auth));
            }

            // tells the console that the guest user is unauthorized,
            // and passes false to the next() functions authed parameter, indicating
            // the custom route defined that the user is un-authed. Some pages such as
            // the profile page or account page will reject access instantly if this field is false.
            warning("Un-authed user with auth header of: ", req.headers[AUTH_HEADER_NAME] || "NONE");
        }
        else
        {
            res.statusCode = 200; // can be changed in next() function
            res.locals.authed = true;
        } 
        /**
         * -----------------
         * -   READ HERE   -
         * -----------------
         * 
         * All custom routes created in this file must return their json response.
         * The returned value can be anything, even null. It is good practice to be an object.
         * 
         * The next function from your route also contains a field in the res object specifying
         * if the user is authenticated or not:
         *  @see res.locals.authed
         * 
         * If your return value is an error, examples like on line 25 show how to properly use them.
         * 
         * @see ServerResponse houses static constants used for different responses. Includes errors.
         * @see ServerSideError An object wrapper for an error recieved from the server.
         * 
         * @see prepareResponsePayload prepareResponsePayload will prepare whatever is returned from next() to be sent back. Please read its contents.
         * 
         */
        res.json(prepareResponsePayload(next()));
    })

    // init routes
    for (const route of Object.values(routes)) {
        try {
            switch (route.method) {
                case "POST": {
                    _app.post(route.method, route.func);
                    break;
                }
                case "DELETE": {
                    _app.delete(route.method, route.func);
                    break;
                }
                case "ALL": {
                    _app.all(route.method, route.func);
                    break;
                }
                case "PUT": {
                    _app.put(route.method, route.func);
                    break;
                }
                default: {
                    _app.get(route.method, route.func);
                    break;
                }
            }
            info("Registered route '" + route.route + "'. ");
        } catch (e) {
            fatal("Route could not be established. Name: " + route.route)
        }
    }

    _app.listen(SERVER_LISTEN_PORT, () => {
        info("Server Listening on " + SERVER_LISTEN_PORT + ".");
    })

这些评论是针对我的合作者的...

这是我定义路线的地方:


/**
 * @type {Object.<string, Route>}
 */
module.exports.routes = {}

/**
 * Route for pinging the server. Mostly for testing.
 */
module.exports.routes.
    ping = new Route("GET", "/ping", async (req, res, next) => null); // all we are looking for is a ping, so no payload body is provided.

module.exports.routes.
    register = new Route("POST", "/register", async (req, res, next) => {
        try {

            info("Route...");

            const { username, email, password } = req;

            if (!vparams(username, email, password)) return new ServerSideError(1, "Please provide all required fields.");

            if (!vname(username)) return new ServerSideError(2, "Invalid Username.");

            if (!vemail(email)) return new ServerSideError(3, "Invalid Email.");

            if (!vpass(password)) return new ServerSideError(4, "Invalid Password.");

            return new Promise((resolve, reject) => {
                sql_addRow(new SQLRow({ username: username, password: password, email: email }, SQLTables.WEB_USERS),
                    (success, error) => {
                        if (error || !success) resolve(new ServerSideError(ServerSideError.ErrorCodes.OTHER, "Something unexpected happened."));

                        resolve(newauth(req));
                    });
            });

        } catch (e) { return new ServerSideError(-2, "Unexpected Error."); }
    });

当我运行

postman
请求
/register
时,我收到此错误。我应该看别的东西吗?我已经检查了我的代码并查看了其他论坛,但他们都说我正在发送 2 个以上的回复,但我在这里看不到。感谢您提前的帮助!

javascript node.js express webserver middleware
1个回答
0
投票

这个本身:

res.json(prepareResponsePayload(next())); 

是一个问题。您既发送响应又调用

next()
,这将导致其他路由能够处理此请求,从而导致发送重复的响应。

如果您发送回复,请勿致电

next()

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