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);
}
}