58 lines
3.0 KiB
JavaScript
58 lines
3.0 KiB
JavaScript
const bodyParser = require('body-parser')
|
||
const formData = require('express-form-data')
|
||
const session = require('express-session')
|
||
const { RedisStore } = require('connect-redis')
|
||
const { getRedisClient, getRawClient } = require('../utils/redisClient')
|
||
const lastOnline = require('./lastOnline')
|
||
|
||
const SESSION_OPTIONS = {
|
||
secret: process.env.SESSION_SECRET || process.env.JWT_SECRET || 'change-me-in-production',
|
||
resave: false,
|
||
saveUninitialized: false,
|
||
cookie: {
|
||
httpOnly: true,
|
||
secure: process.env.NODE_ENV === 'production',
|
||
sameSite: 'lax',
|
||
},
|
||
}
|
||
|
||
// قبلاً MemoryStoreِ پیشفرضِ express-session بود — برای production مناسب نیست (نه
|
||
// بین چند اینستنسسرور مشترکه، نه محدودیتی داره). الان وقتی Redis وصله از یه store
|
||
// مشترک استفاده میشه. عین ratedLimiter (createRateLimiter.js): دو نمونهی کاملاً
|
||
// جدا ساخته میشه و روی *هر* درخواست بر اساسِ آمادهبودنِ فعلیِ Redis سوییچ میشه —
|
||
// نه اینکه همیشه به Redis وصل بشه و فقط منتظرِ خطا بمونه. اون روش (client خام،
|
||
// بدون چکِ آمادهبودن) وقتی Redis اصلاً هیچوقت در دسترس نبود (مثلاً یه دیپلویِ
|
||
// تازه که هنوز Redis روش ست نشده)، هر درخواست رو تا انقضای connectTimeout کند
|
||
// میکرد؛ این نسخه اون تأخیر رو صفر میکنه چون اصلاً منتظرِ Redis نمیمونه
|
||
const redisSession = session({
|
||
...SESSION_OPTIONS,
|
||
store: new RedisStore({ client: getRawClient(), prefix: 'sess:' }),
|
||
})
|
||
const memorySession = session(SESSION_OPTIONS)
|
||
|
||
// نکته: اگه Redis وسطِ یه session بیفته (بعد از ساختهشدن یه سشنِ Redis-محور)،
|
||
// سوییچ به memorySession یعنی اون سشنِ خاص موقتاً دیده نمیشه — قابلقبوله چون این
|
||
// اپ اصلیترین احرازهویتش JWTه، نه سشن (req.session جای دیگهای توی این کدبیس
|
||
// استفاده نمیشه)
|
||
function dispatchSession (req, res, next) {
|
||
const store = getRedisClient() ? redisSession : memorySession
|
||
store(req, res, (err) => {
|
||
if (err) {
|
||
// fallback نهایی برای همون ریسِ نادرِ «Redis درست وسطِ همین درخواست قطع شد» —
|
||
// بهجای next(err) (که express-session پیشفرضش ۵۰۰-کردنِ کل درخواسته)، فقط
|
||
// لاگ میکنیم و بدون سشن ادامه میدیم
|
||
console.error('[session] store error — continuing without session:', err.message)
|
||
return next()
|
||
}
|
||
next()
|
||
})
|
||
}
|
||
|
||
module.exports = (app) => {
|
||
app.use(formData.parse())
|
||
app.use(bodyParser.json())
|
||
app.use(bodyParser.urlencoded({ extended: true }))
|
||
app.use(dispatchSession)
|
||
app.use(lastOnline)
|
||
}
|