diff --git a/JavaScript/client.js b/JavaScript/client.js index 8644fa8..56eb4ef 100644 --- a/JavaScript/client.js +++ b/JavaScript/client.js @@ -27,7 +27,11 @@ class Client { static async getInstance(req, res) { const client = new Client(req, res); - await Session.restore(client); + try { + await Session.restore(client); + } catch (err) { + console.log(err.message); + } return client; } @@ -58,7 +62,7 @@ class Client { sendCookie() { const { res, preparedCookie } = this; - if (preparedCookie.length && !res.headersSent) { + if (preparedCookie.length > 0 && !res.headersSent) { console.dir({ preparedCookie }); res.setHeader('Set-Cookie', preparedCookie); } diff --git a/JavaScript/server.js b/JavaScript/server.js index daa7125..d0ab5c6 100644 --- a/JavaScript/server.js +++ b/JavaScript/server.js @@ -12,9 +12,8 @@ const routing = { return `Session token is: ${client.token}`; }, '/destroy': async (client) => { - const result = `Session destroyed: ${client.token}`; - Session.delete(client); - return result; + const { token } = await Session.delete(client); + return token ? `Session destroyed: ${token}` : 'Session not found!'; }, '/api/method1': async (client) => { if (client.session) { @@ -24,18 +23,20 @@ const routing = { return { data: 'access is denied' }; } }, - '/api/method2': async (client) => ({ - url: client.req.url, - headers: client.req.headers, - }), - '/api/method3': async (client) => { - if (client.session) { - return [...client.session.entries()] - .map(([key, value]) => `${key}: ${value}
`) - .join(); - } - return 'No session found'; + '/api/method2': async (client) => { + if (client.session) client.session.set('method2', 'called'); + return { + url: client.req.url, + headers: client.req.headers, + }; }, + '/api/method3': async (client) => { + if (!client.session) return 'No session found'; + client.session.set('method3', 'called'); + return [...client.session.entries()] + .map(([key, value]) => `${key}: ${value}
`) + .join(); + } }; const types = { @@ -45,6 +46,11 @@ const types = { undefined: () => 'not found', }; +const httpError = (res, code, msg) => { + res.statusCode = code; + res.end(msg); +}; + http.createServer(async (req, res) => { const client = await Client.getInstance(req, res); const { method, url, headers } = req; @@ -53,20 +59,19 @@ http.createServer(async (req, res) => { res.on('finish', () => { if (client.session) client.session.save(); }); - if (!handler) { - res.statusCode = 404; - res.end('Not found 404'); - return; - } - handler(client).then((data) => { - const type = typeof data; - const serializer = types[type]; - const result = serializer(data); - client.sendCookie(); - res.end(result); - }, (err) => { - res.statusCode = 500; - res.end('Internal Server Error 500'); - console.log(err); - }); + if (!handler) return void httpError(res, 404, 'Not Found 404'); + handler(client) + .then( + (data) => { + const type = typeof data; + const serializer = types[type]; + const result = serializer(data); + client.sendCookie(); + res.end(result); + }, + (err) => { + httpError(res, 500, 'Server Error 500'); + console.log(err); + } + ); }).listen(8000); diff --git a/JavaScript/session.js b/JavaScript/session.js index ea66627..502cded 100644 --- a/JavaScript/session.js +++ b/JavaScript/session.js @@ -36,30 +36,33 @@ class Session extends Map { return session; } - static restore(client) { + static async restore(client) { const { cookie } = client; - if (!cookie) return; + if (!cookie) throw new Error('No session'); const sessionToken = cookie.token; - if (sessionToken) { - return new Promise((resolve, reject) => { - storage.get(sessionToken, (err, session) => { - if (err) reject(new Error('No session')); - Object.setPrototypeOf(session, Session.prototype); - client.token = sessionToken; - client.session = session; - resolve(session); - }); - }); + if (!sessionToken) throw new Error('No session'); + try { + const session = await storage.get(sessionToken); + Object.setPrototypeOf(session, Session.prototype); + client.token = sessionToken; + client.session = session; + return session; + } catch (err) { + throw new Error('No session'); } } - static delete(client) { + static async delete(client) { const { token } = client; - if (token) { - client.deleteCookie('token'); - client.token = undefined; - client.session = null; - storage.delete(token); + if (!token) return false; + client.deleteCookie('token'); + client.token = undefined; + client.session = null; + try { + await storage.delete(token); + return { token }; + } catch (err) { + return { token: undefined }; } } diff --git a/JavaScript/storage.js b/JavaScript/storage.js index a114315..a5f25f2 100644 --- a/JavaScript/storage.js +++ b/JavaScript/storage.js @@ -1,63 +1,60 @@ 'use strict'; -const fs = require('node:fs'); +const fsp = require('node:fs/promises'); const path = require('node:path'); const v8 = require('node:v8'); const PATH = `${__dirname}/sessions`; -const safePath = (fn) => (token, ...args) => { - const callback = args[args.length - 1]; +const exist = async (file) => { + const toBool = [() => true, () => false]; + const isExist = await fsp.access(file).then(...toBool); + return isExist; +}; + +const safePath = (fn) => async (token, ...args) => { if (typeof token !== 'string') { - callback(new Error('Invalid session token')); - return; + throw new Error('Invalid session token'); } const fileName = path.join(PATH, token); if (!fileName.startsWith(PATH)) { - callback(new Error('Invalid session token')); - return; + throw new Error('Invalid session token'); + } + const tokenExist = await exist(fileName); + if (!tokenExist) { + console.log('Token not found!'); + throw new Error('Invalid session token'); } - fn(fileName, ...args); + return await fn(fileName, ...args); }; -const readSession = safePath(fs.readFile); -const writeSession = safePath(fs.writeFile); -const deleteSession = safePath(fs.unlink); +const readSession = safePath(fsp.readFile); +const writeSession = safePath(fsp.writeFile); +const deleteSession = safePath(fsp.unlink); class Storage extends Map { - get(key, callback) { + async get(key) { const value = super.get(key); - if (value) { - callback(null, value); - return; - } - readSession(key, (err, data) => { - if (err) { - callback(err); - return; - } - console.log(`Session loaded: ${key}`); - const session = v8.deserialize(data); - super.set(key, session); - callback(null, session); - }); + if (value) return value; + const data = await readSession(key); + console.log(`Session loaded: ${key}`); + const session = v8.deserialize(data); + super.set(key, session); + return session; } - save(key) { + async save(key) { const value = super.get(key); if (value) { const data = v8.serialize(value); - writeSession(key, data, () => { - console.log(`Session saved: ${key}`); - }); + await writeSession(key, data); + console.log(`Session saved: ${key}`); } } - delete(key) { + async delete(key) { console.log('Delete: ', key); - deleteSession(key, () => { - console.log(`Session deleted: ${key}`); - }); + return await deleteSession(key); } }