I'm writing a session library for Express.js that stores the sessions in encrypted files. The basic interfaces hierarchy is:
export interface Current<T = any> {
load(): Promise<T>;
save(value: T): Promise<void>;
}
export interface Manager {
current<T = any>(): Current<T>;
create(): Promise<void>;
delete(): Promise<void>;
rewind(): void;
}
declare global {
namespace Express {
export interface Request {
session: Manager;
}
}
}
Every session is stored in a JSON file, which name is a unique hash id. That hash is returned to the client as a cookie. The implementation it's like that:
import { sessionCrossover } from '.';
import express from 'express';
const app = express();
app.use(sessionCrossover({
path: './data',
expires: 1000 * 10,
hashLength: 126
}));
For create a new session:
// The data structure of every session in this example
interface Data {
id: number;
value: string;
}
// Create an endpoint for create a new session
app.get('/create', async (req, res) => {
try {
// Get the current session instance
const current = req.session.current<Data>();
if (!current) {
// Create a new session instance
await req.session.create();
// Save in the current session the data. Just in this
// case, if the session file doesn't exist, it will
// be created. This method throws the error...
await req.session
.current<Data>()
.save({
id: ++id,
value: new Date().toJSON()
});
res.json('Session created sucessfully');
} else {
req.session.rewind();
res.json('Session rewinded...');
}
} catch (err) {
console.error(err);
res.json(err);
}
});
Inside of the method that throws the error:
import { File } from '../tool/fsys';
import { Current } from './interfaces';
export class CurrentSession<T = any> implements Current<T> {
private _file: File;
// The related method
save(value: T): Promise<void> {
if (!this._killed) {
const text = JSON.stringify(value, null, ' ');
const byte = Buffer.from(text, 'utf8');
// Throws the error
return this._file.write(byte);
} else {
return Promise.resolve();
}
}
}
And the File class:
import * as fs from 'fs';
import * as fsPromises from 'fs/promises';
export class File extends FSys {
// The related method
public write(byte: Buffer): Promise<void> {
// this._path it's a protected property of FSys
return fsPromises.writeFile(this._path, byte);
}
}
You can set the current hash length in the middleware shown before. The problem is this:
- When you set a hash of a 126 bytes or more, node.js throws an "ENOENT" error (path not found).
- When the hash is 125 bytes or less the file with the session it's created normally.
My questions are:
- Why node.js thows an "ENOENT" (path not found error) when i try to create a file with a large filename?
- Exists a method to detect a "too large filesize" exception in windows?
Observations:
I tried with different hash byte length. The paths in those cases, are:
- Hash length = 8; OK
C:\Projects\Node.JS\modules\session-crossover\data\be49c866b0181718.json
- Hash length = 64; OK
C:\Projects\Node.JS\modules\session-crossover\data\419410c8db26d74563e31b3c0a12e9fb12d31951abe6b280869af47db088c9acaf251de12cd6b6fc51bf3182fa07597add2b48825498d869b99e914c64d42efa.json
- Hash length = 125; OK
C:\Projects\Node.JS\modules\session-crossover\data\b6f4026e893fb053e626ca3318771a70e0802ca10bfc4ea018e18f35b04aa7f9e365a9883a35eea381d9cb9ad2ca11c8961e0096aacd2802e9e0b4cd96920c073800f40a1224d99a093f7fa0b4eca8799bc84c4fa84db2b8b62df211824271c4d908d3d62defa6f1890e613e04af86bcd04379b57ab3728e0366ed42c9.json
- Hash length = 126; "ENOENT"
C:\Projects\Node.JS\modules\session-crossover\data\7784ae9a697eb7e5a2ccdf7a9b27c4d182e1e637da4efc47d21a1d48f208f1058bf40f6026dccb79702ea61ea3f4ca307fdeb960a38c89187b0c1b66395934a802ee62769810bd191eb85636d6a86c900299b68fcc1ad6ccfbd83aba863fc181a522cd22d0671148b56d6e4c8051b4366439d6855597caad0eb6a4bba043.json