将 Express.js 4 的 res.status(401) 链接到重定向
Chaining Express.js 4's res.status(401) to a redirect
如果请求用户未通过身份验证,我想发送响应代码 401,但我也想在请求是 HTML 请求时重定向。我发现 Express 4 不允许这样做:
res.status(401).redirect('/login')
有谁知道处理这个问题的方法吗?这可能不是 Express 的限制,因为我要求本质上传递两个 headers,但我不明白为什么会这样。我应该能够一次性传递 "not authenticated" 响应并重定向用户。
您当然可以在发送 401 页面的同时发送 Location: /login
header,但是,这是 ill-advised,大多数浏览器不会遵循它,因为 rfc2616.
克服这个问题的一种方法是在 401
页面上同时提供 <meta http-equiv="refresh" content="0; url=/login">
:
res.set('Content-Type', 'text/html');
res.status(401).send('<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0; url=/login"></head></html>');
发回新位置的方法存在一些细微差别 header。
与redirect
:
app.get('/foobar', function (req, res) {
res.redirect(401, '/foo');
});
// Responds with
HTTP/1.1 401 Unauthorized
X-Powered-By: Express
Location: /foo
Vary: Accept
Content-Type: text/plain; charset=utf-8
Content-Length: 33
Date: Tue, 07 Apr 2015 01:25:17 GMT
Connection: keep-alive
Unauthorized. Redirecting to /foo
app.get('/foobar', function (req, res) {
res.status(401).location('/foo').end();
});
// Responds with
HTTP/1.1 401 Unauthorized
X-Powered-By: Express
Location: /foo
Date: Tue, 07 Apr 2015 01:30:45 GMT
Connection: keep-alive
Transfer-Encoding: chunked
使用 redirect
的原始(不正确)方法:
app.get('/foobar', function (req, res) {
res.status(401).redirect('/foo')();
});
// Responds with
HTTP/1.1 302 Moved Temporarily
X-Powered-By: Express
Location: /foo
Vary: Accept
Content-Type: text/plain; charset=utf-8
Content-Length: 38
Date: Tue, 07 Apr 2015 01:26:38 GMT
Connection: keep-alive
Moved Temporarily. Redirecting to /foo
所以看起来 redirect
将放弃任何以前的状态代码并发送默认值(除非在方法调用中指定)。这是有道理的,因为在 Express 中使用了中间件。如果您有一些全局中间件对所有请求执行 pre-checks(例如检查正确接受 header 等),它们将不知道重定向请求。然而,身份验证中间件会因此知道覆盖任何以前的设置以正确设置它们。
更新:如以下评论所述,即使 Express 可以发送具有位置 header 的 4XX 状态代码,并不意味着根据规范,请求客户端可以理解它是可接受的响应。事实上,大多数人会忽略位置 header 除非状态代码是 3XX 值。
我遇到了同样的问题,决定使用会话来处理这种工作。
我不想有一个中间视图...
使用下面的代码,我可以重定向到主页,该主页将使用 401 未经授权的代码呈现。
app.get('patternForbiddenRoute', (req, res, next) => {
// previousCode
if (notForbidden === true) {
return res.render("a_view");
}
req.session.httpCode = 401;
res.redirect('patternHomeRoute');
});
app.get('patternHomeRoute', (req, res, next) => {
res.render("my_home_view", {}, (error, html) => {
// ... handle error code ...
const httpCode = req.session.httpCode;
if (httpCode !== undefined) {
delete req.session.httpCode;
res.status(httpCode);
}
res.send(html);
}));
});
如果请求用户未通过身份验证,我想发送响应代码 401,但我也想在请求是 HTML 请求时重定向。我发现 Express 4 不允许这样做:
res.status(401).redirect('/login')
有谁知道处理这个问题的方法吗?这可能不是 Express 的限制,因为我要求本质上传递两个 headers,但我不明白为什么会这样。我应该能够一次性传递 "not authenticated" 响应并重定向用户。
您当然可以在发送 401 页面的同时发送 Location: /login
header,但是,这是 ill-advised,大多数浏览器不会遵循它,因为 rfc2616.
克服这个问题的一种方法是在 401
页面上同时提供 <meta http-equiv="refresh" content="0; url=/login">
:
res.set('Content-Type', 'text/html');
res.status(401).send('<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0; url=/login"></head></html>');
发回新位置的方法存在一些细微差别 header。
与redirect
:
app.get('/foobar', function (req, res) {
res.redirect(401, '/foo');
});
// Responds with
HTTP/1.1 401 Unauthorized
X-Powered-By: Express
Location: /foo
Vary: Accept
Content-Type: text/plain; charset=utf-8
Content-Length: 33
Date: Tue, 07 Apr 2015 01:25:17 GMT
Connection: keep-alive
Unauthorized. Redirecting to /foo
app.get('/foobar', function (req, res) {
res.status(401).location('/foo').end();
});
// Responds with
HTTP/1.1 401 Unauthorized
X-Powered-By: Express
Location: /foo
Date: Tue, 07 Apr 2015 01:30:45 GMT
Connection: keep-alive
Transfer-Encoding: chunked
使用 redirect
的原始(不正确)方法:
app.get('/foobar', function (req, res) {
res.status(401).redirect('/foo')();
});
// Responds with
HTTP/1.1 302 Moved Temporarily
X-Powered-By: Express
Location: /foo
Vary: Accept
Content-Type: text/plain; charset=utf-8
Content-Length: 38
Date: Tue, 07 Apr 2015 01:26:38 GMT
Connection: keep-alive
Moved Temporarily. Redirecting to /foo
所以看起来 redirect
将放弃任何以前的状态代码并发送默认值(除非在方法调用中指定)。这是有道理的,因为在 Express 中使用了中间件。如果您有一些全局中间件对所有请求执行 pre-checks(例如检查正确接受 header 等),它们将不知道重定向请求。然而,身份验证中间件会因此知道覆盖任何以前的设置以正确设置它们。
更新:如以下评论所述,即使 Express 可以发送具有位置 header 的 4XX 状态代码,并不意味着根据规范,请求客户端可以理解它是可接受的响应。事实上,大多数人会忽略位置 header 除非状态代码是 3XX 值。
我遇到了同样的问题,决定使用会话来处理这种工作。
我不想有一个中间视图...
使用下面的代码,我可以重定向到主页,该主页将使用 401 未经授权的代码呈现。
app.get('patternForbiddenRoute', (req, res, next) => {
// previousCode
if (notForbidden === true) {
return res.render("a_view");
}
req.session.httpCode = 401;
res.redirect('patternHomeRoute');
});
app.get('patternHomeRoute', (req, res, next) => {
res.render("my_home_view", {}, (error, html) => {
// ... handle error code ...
const httpCode = req.session.httpCode;
if (httpCode !== undefined) {
delete req.session.httpCode;
res.status(httpCode);
}
res.send(html);
}));
});