看到其他同学提问,同样的问题有同学说是未设置req.session={}
的问题,我一层层排查了,req.session
打印的时候确实是个空对象,是有值的,但是我最后req.session.username = data.username
时就是无法赋值,请老师帮忙看一下,谢谢老师。
user.js
const {
login
} = require('../controller/user');
const { SuccessModel, ErrorModel } = require('../model/resModel')
const { set } = require('../db/redis');
const handleUserRouter = (req, res) => {
const { method } = req;
// 登录
if (method === 'GET' && req.path === '/api/user/login') {
const { username, password } = req.query;
const result = login(username, password);
return result.then(data => {
if(data.username) {
// 设置session
req.session.username = data.username;
req.session.realname = data.realname;
// console.log('req.session is', req.session);
// 同步到 redis 中, 这样下次访问登录验证时就可以从redis直接拿session用
set(req.sessionId, req.session);
return new SuccessModel();
}
return new ErrorModel('login fail');
})
}
//登录验证测试
if (method === 'GET' && req.path === '/api/user/login-test') {
console.log(req.session, req.session.username);
if(req.session.username) {
return Promise.resolve(new SuccessModel({
session: req.session
}));
}
return Promise.resolve(new ErrorModel('尚未登录'));
}
}
module.exports = handleUserRouter;
app.js
const { reject } = require('lodash');
const { resolve } = require('path');
const { get, set } = require('./src/db/redis');
const querystring = require('querystring');
const handleBlogRouter = require('./src/router/blog');
const handleUserRouter = require('./src/router/user');
// 过期时间
const getCookieExpires = () => {
const d = new Date();
d.setTime(d.getTime() + (24 * 60 * 60 * 1000)); //当前时间加一天过期
// console.log(d.toGMTString());
return d.toGMTString();
}
// 用于处理postData
const getPostData = (req) => {
const promise = new Promise((resolve, reject) => {
if(req.method !== 'POST') {
resolve({});
return;
}
if(req.headers['content-type'] !== 'application/json') {
resolve({});
return;
}
let postData = '';
req.on('data', chunk => {
postData += chunk.toString();
})
req.on('end', () => {
if (!postData) {
resolve({});
return;
}
resolve(
JSON.parse(postData)
)
})
})
return promise;
}
const serverHandle = (req, res) => {
// 设置返回格式 JSON
res.setHeader('Content-type', 'application/json');
const { url } = req;
req.path = url.split('?')[0];
// 解析query
req.query = querystring.parse(url.split('?')[1]);
// 解析cookie
req.cookie = {};
const cookieStr = req.headers.cookie || '';
cookieStr.split(';').forEach(item => {
// 异常处理
if(!item) {
return;
}
const arr = item.split('=');
const key = arr[0].trim(); // 避免空格
const value = arr[1];
// console.log(key, value);
req.cookie[key] = value;
})
// 使用redis解析session
let { userid } = req.cookie;
let needSetCookie = false;
if (!userid) {
needSetCookie = true;
userid = `${Date.now()}_${Math.random()}`;
// 初始化 redis 中的session值
set(userid, {});
}
// 获取 session
req.sessionId = userid;
get(req.sessionId).then(sessionData => {
if (sessionData == null) {
// 初始化 redis 中的session
set(req.sessionId, {});
// 设置session
req.session = {};
} else {
req.session = sessionData;
}
console.log('req.session', req.session);
// 处理postData
return getPostData(req);
}).then(postData => {
req.body = postData;
const blogResult = handleBlogRouter(req, res);
if (blogResult) {
blogResult.then(blogData => {
if (needSetCookie) {
res.setHeader('Set-cookie', `userid=${userid};path=/; httpOnly; expires=${getCookieExpires()}`);
}
res.end(
JSON.stringify(blogData)
)
})
return;
}
const userResult = handleUserRouter(req, res);
if (userResult) {
userResult.then(userData => {
if (needSetCookie) {
res.setHeader('Set-cookie', `userid=${userid};path=/; httpOnly; expires=${getCookieExpires()}`);
}
res.end(
JSON.stringify(userData)
)
})
return;
}
// 未命中返回404
res.writeHead(404, { 'Content-type': 'text/plain' });
res.write('404 Not Found\n');
res.end();
})
}
module.exports = serverHandle
redis.js
const redis = require('redis');
const { REDIS_CONF } = require('../conf/db');
// 创建客户端
const redisClient = redis.createClient(REDIS_CONF.port, REDIS_CONF.host);
redisClient.on('error', err => {
console.log(err);
})
function set(key, val) {
if (typeof val === 'object') {
val = JSON.stringify(val);
}
redisClient.set(key, val, redis.print); //Reply: OK
}
function get(key, val) {
const promise = new Promise((resolve, reject) => {
redisClient.get(key, (err, val) => {
if (err) {
reject(err);
ReadableStreamDefaultController;
}
if (val == null) {
resolve(null);
return;
}
try {
resolve(
JSON,parse(val)
)
} catch (ex) {
resolve(val);
}
})
})
return promise;
}
module.exports = {
set,
get
}