【发布时间】:2020-12-12 07:55:50
【问题描述】:
当我在同一页面上发出两个同步的连续提取请求时,服务器会为该客户端创建两个不同的会话。这是因为第二个请求发送到服务器之前第一个响应将 Set-Cookie 标头发送回客户端。
控制台显示两个请求都没有发送 cookie。因此,两个响应都创建了一个新会话。
-----------'/first' request------------
'req.headers.cookie: undefined
'req.sessionID: uZCc-2EtuOIdqD5xfcBCBLQjZbRmy29k
'/first' Set-Cookie header: connect.sid=s%3AuZCc-2EtuOIdqD...
-----------'/second' request------------
'req.headers.cookie: undefined
'req.sessionID: Gzr5CPYvE5deGA-Ul7EwOzHbaWFtpXR3
'/second' Set-Cookie header: connect.sid=s%3AGzr5CPYvE5deGA...
当您取消注释 // await addNSecondsDelay(5);(请记住清除要复制的 cookie)以创建 5 秒延迟时,您可以进一步看到此问题是由于第二个请求触发过快引起的。这将只创建一个会话。
我不希望每次新客户访问具有多个请求的页面时都创建额外的未使用会话。我可以想出一些方法来解决这个问题——比如异步调用 fetch——但这似乎不适合更复杂的情况,比如动态创建 html 页面并且你不能将每个动态生成的 fetch 调用链接在一起零件。这似乎也会减慢页面加载速度。
是否有适当的方法来确保不创建两个会话?
后端服务器
// other-server.js
const express = require('express');
const session = require('express-session');
const bodyParser = require('body-parser');
const app = express();
const sess = {
saveUninitialized: false,
resave: false,
secret: 'very secret 12345',
cookie: {
sameSite: true,
secure: false,
},
};
app.use(bodyParser.json());
app.use(
bodyParser.urlencoded({
extended: true,
})
);
app.use(session(sess));
app.use((req, res, next) => {
console.log(`\n-----------'${req.path}' request------------`);
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With, Accept, Content-Type');
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:5001');
res.setHeader('Access-Control-Allow-Credentials', true);
res.setHeader(
'Access-Control-Allow-Methods',
'GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH'
);
res.on('close', function () {
console.log(
`'${req.path}' Set-Cookie header: ${res.getHeaders()['set-cookie'][0].slice(0, 30)}...`
);
});
req.session.a = 'hi';
console.log(`'req.headers.cookie: ${req.headers.cookie}`);
console.log(`'req.sessionID: ${req.sessionID}`);
next();
});
app.post('/first', (req, res) => {
res.json({ message: "1st fetch's response" });
});
app.post('/second', (req, res) => {
res.json({ message: "2nd fetch's response" });
});
app.listen(4001, () => {
console.log('start');
});
前端服务器
// server.js
const express = require('express');
const app = express();
app.use(express.static('./public'));
app.listen(5001);
index.html
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<script>
const addNSecondsDelay = (n) => {
console.log('5 second delay ...');
return new Promise((resolve) => {
setTimeout(() => {
resolve();
}, n * 1000);
});
};
const asyncFunctionCall = async () => {
fetch('http://localhost:4001/first', {
method: 'POST',
credentials: 'include',
})
.then((response) => {
return response.json();
})
.then((json) => {
console.log('Received: ' + JSON.stringify(json));
});
// await addNSecondsDelay(5);
fetch('http://localhost:4001/second', {
method: 'POST',
credentials: 'include',
})
.then((response) => {
return response.json();
})
.then((json) => {
console.log('Received: ' + JSON.stringify(json));
});
};
asyncFunctionCall();
</script>
</body>
</html>
【问题讨论】:
-
你能在加载网页的服务器上运行 API 吗?如果是这样,那么在您的任何 Javascript 运行之前,将网页加载到浏览器中的行为就已经在浏览器中设置了会话 cookie。
-
@jfriend00 对于我的具体用例,我希望将它们分开,但很高兴知道
-
我实际上意识到我不需要两台不同的服务器,所以我接受了这个建议。谢谢
标签: node.js express http session cookies