node-express 应用程序:如果中间件函数位于堆栈的最后,我们是否需要显式发送响应?

node-express application: do we need to send the response explicitly if the middleware function is last on stack?

我 运行 遇到一个问题,如果我没有明确发回响应,我的 Express 应用程序会向浏览器发回 'Cannot call /POST' 消息。我使用 MongoDB 作为后端并表示为路由框架。 请参考 'Router code'.

部分的最后一个(评论)

用户模型代码:

UserSchema.pre("save", function(done){
var user = this;

console.log("Processing before saving the user.")

if(!user.isModified("password")){
    //if password isn't changed, then don't do any processing on pwd to re-hash it.
    done();
}

//progress function - optional parameter for bcrypt's hash func.
var progressFunction = function(){} ;

bcrypt.genSalt(SALT_FACTOR, function(err, salt){
    if(err){return done(err);}

    //console.log("Computing hash for pwd.");

    bcrypt.hash(user.password, salt, progressFunction, function(err, hashedPassword){
        if(err){return done(err);}

        user.password = hashedPassword;

        //console.log("user-built logic done. invoking next middleware.");

        done();

        //console.log("next middleware exec done");
    });
});
});

路由器代码:

var User = require("../models/user");
var router = express.Router();
router.post("/signup", function(req, res, next) {
    var username = req.body.username;
    var password = req.body.password;

    User.findOne({username : username}, function(err, existingUser){
        if(err){return next(err);}

        if(existingUser){
            req.flash("error", "User with this username exist already. Try different username.");

            return res.redirect("/signup");
        }

        //create and save a newly signedUp user.
        var newUser = new User({
            username : username,
            password : password
        });
        newUser.save(next); //call model's processing save
        //res.send(200); //if i dont send this response back, i get the error mentioned above.
    });
});

我的路由器是启动应用服务器之前堆栈中的最后一个中间件。

//mount routes
app.use(routes);
app.listen(app.get("port"), function(){
    console.log("Server started on port : " + app.get("port"));
});

如果有人能解释这种行为背后的原因,那就太好了。

要成为一个正常运行的服务器,您需要在某个地方发送对任何传入 HTTP 请求的响应。这是因为客户端发送请求,然后等待响应。获得响应是它知道请求已成功接收和理解的唯一方式。

Express 对您的中间件已经完成或未完成的事情一无所知,因此它根本不知道作为默认响应发送的适当响应是什么。你可能已经处理过它,也可能没有。而且,事实上,如果没有其他处理程序接受响应,许多快递服务器被手动配置为默认为 404。而且,这是通过简单地让链中的最后一个处理程序发送 404 来完成的。如果请求一直传递到最后一个处理程序,那么肯定没有其他处理程序处理过该请求,因此它被认为是未处理的。

虽然在这种情况下这可能不是您想要的(因为您已经处理了请求),但您可以通过将此中间件添加为应用中的最后一个请求处理程序来添加默认的 404 处理程序:

app.use(function (req, res, next) {
  res.status(404).send('Sorry cant find that!')
});

您可以将其更改为默认的 200 状态,但这样您会为不存在的路由返回 200,这不是配置服务器的理想方式。

至于为什么这样做,那是因为Express或HTTP服务器本身无法知道适当的响应应该是什么。您知道什么是适当响应的代码必须发送它。