routing-controllers
routing-controllers copied to clipboard
question: It does't work with express-mysql-session
I was trying to...
use this library with express-mysql-session
, but it doesn't work.
The problem:
The error occurs when...
- Run the code below.
- Access to
localhost:3000
(Got a session-id) - Access to
localhost:3000/secret
then I expect to get an Unauthorized Error(401) but get a net::ERR_CONTENT_LENGTH_MISMATCH
import "reflect-metadata";
import express from "express";
import session from "express-session";
import MySQLStoreClassFactory from "express-mysql-session";
import {
Authorized,
Controller,
Get,
Session,
useExpressServer,
} from "routing-controllers";
const PORT = 3000;
const SECRET = "secret";
const DB_HOST = "localhost";
const DB_PORT = 3306;
const DB_USER = "root";
const DB_PASS = "password";
const DB_NAME = "express_session";
const app = express();
const MySQLSessionStore = MySQLStoreClassFactory(session as any);
const sessionStore = new MySQLSessionStore({
host: DB_HOST,
port: DB_PORT,
user: DB_USER,
password: DB_PASS,
database: DB_NAME,
});
@Controller()
class IndexController {
@Get("/")
index(@Session() sess: any) {
sess.views = (sess.views || 0) + 1;
return "Hello World";
}
@Authorized()
@Get("/secret")
secret() {
return "Secret Page";
}
}
app.use(
session({
secret: SECRET,
store: sessionStore,
resave: false,
saveUninitialized: false,
})
);
useExpressServer(app, {
controllers: [IndexController],
authorizationChecker: () => false,
});
app.listen(PORT, () => {
console.log(`Server is listening on port ${PORT}`);
});
I think this is because...
https://github.com/typestack/routing-controllers/blob/24556885e58e1022531881eecb963c363e9933a9/src/driver/express/ExpressDriver.ts#L384-L391
Here, the next
callback is called after the res.send
method was called. (ref #589)
the res.send
method calls res.end
internally and when using express-session
library, res.end
method is proxied.
In this proxy, the first ${chunk.length - 1} bytes of the data chunk will be written immediately but the remaining one byte will be written after saving/touching session data to the data store asynchronously.
ref https://github.com/expressjs/session/blob/a8641429502fcc076c4b2dcbd6b2320891c1650c/index.js#L334-L343
if (shouldSave(req)) {
req.session.save(function onsave(err) {
if (err) {
defer(next, err);
}
writeend();
});
return writetop();
} else if (...) {
On the other hand, when the next
callback is called with an error, the error will be passed to this method.
In this method, if the headers of the response have already been sent, the socket of the response will be destroyed. ref https://github.com/pillarjs/finalhandler/blob/15e78cab32ecbd4993d1575a065963b238336df9/index.js#L126-L130
So, when the socket is destroyed before the last byte of the data chunk is written, the CONTENT_LENGTH_MISMATCH
error happens. (actually, content length was mismatched by 1 byte)
As mentioned in #589, the next
callback seems strange.
But this issue is about a very ordinary use case, so I feel there is some best practice I don't know.
So, I want to know how to set up this amazing library with express-mysql-session
if you have any idea.