Skip to content

Commit

Permalink
feat(API): expose session as req.session instead of arg to handler (#11)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: session is now exposed in req.session as this is the way
express-session does too
  • Loading branch information
vvo authored Mar 9, 2020
1 parent 4e2d6fa commit a58cad5
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 36 deletions.
23 changes: 12 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ Store passwords in secret environment variables on your platform.
```js
import withIronSession from "iron-session";

async function handler(req, res, session) {
session.set("user", {
async function handler(req, res) {
req.session.set("user", {
id: 230,
admin: true
});
await session.save();
await req.session.save();
res.send("Logged in");
}

Expand All @@ -51,7 +51,7 @@ export default withIronSession(handler, {
import withIronSession from "iron-session";

function handler(req, res, session) {
const user = session.get("user");
const user = req.session.get("user");
res.send({ user });
}

Expand All @@ -66,7 +66,7 @@ export default withIronSession(handler, {
import withIronSession from "iron-session";

function handler(req, res, session) {
session.destroy();
req.session.destroy();
res.send("Logged out");
}

Expand All @@ -79,13 +79,13 @@ export default withIronSession(handler, {

### withIronSession(handler, {password, ttl, cookieName, cookieOptions})

### session.set
### req.session.set

### session.get
### req.session.get

### session.setFlash
### req.session.setFlash

### session.destroy
### req.session.destroy

## FAQ

Expand All @@ -96,6 +96,7 @@ This makes your sessions stateless: you do not have to store session data on you
- you cannot invalidate a seal when needed because there's no state stored on the server-side about them. We consider that the way the cookie is stored reduces the possibility for this eventuality to happen.
- application not supporting cookies won't work, but you can use [iron-store](https://github.com/vvo/iron-store/) to implement something similar. In the future we could allow `next-iron-session` to accept [basic auth](https://tools.ietf.org/html/rfc7617) or bearer token methods too. Open an issue if you're interested.
- on most browsers, you're limited to 4,096 bytes per cookie. To give you an idea, a `next-iron-session` cookie containing `{user: {id: 230, admin: true}}` is 358 bytes signed and encrypted: still plenty of available cookie space in here.
- performance: crypto on server side could be slow, if that's the case let me know. Also cookies are sent to every requests to your website, even images, so this could be an issue

Now that you know the drawbacks, you can decide if they are an issue for your application or not.

Expand All @@ -111,9 +112,9 @@ Depending on your own needs and preferences, `next-iron-session-cookie` may or m

## Project status

This is a recent library I authored because I needed it. While @hapi/iron is battle-tested and [used in production on a lot of websites](https://hapi.dev/), this library is not. Please use it at your own risk.
This is a recent library I authored because I needed it. While @hapi/iron is battle-tested and [used in production on a lot of websites](https://hapi.dev/), this library is not (yet!). Please use it at your own risk.

If you find bugs or have API ideas, create an issue.
If you find bugs or have API ideas, [create an issue](https://github.com/vvo/next-iron-session/issues).

## 🤓 References

Expand Down
4 changes: 3 additions & 1 deletion lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ export default function withIronSession(
}
};

return withIronSessionWrapperHandler(req, res, session);
req.session = session;

return withIronSessionWrapperHandler(req, res);
};
}
44 changes: 20 additions & 24 deletions lib/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ test("ironStore(handler) without a password", () => {

test("ironStore(handler, {password})", () => {
return new Promise(done => {
const handler = (req, res, session) => {
expect(session).toMatchInlineSnapshot(`
const handler = req => {
expect(req.session).toMatchInlineSnapshot(`
Object {
"destroy": [Function],
"get": [Function],
Expand All @@ -38,10 +38,10 @@ test("ironStore(handler, {password})", () => {
});
});

test("session.set", () => {
test("req.session.set", () => {
return new Promise(done => {
const handler = (req, res, session) => {
expect(session.set("user", { id: 20 })).toMatchInlineSnapshot(`
const handler = req => {
expect(req.session.set("user", { id: 20 })).toMatchInlineSnapshot(`
Object {
"id": 20,
}
Expand All @@ -58,14 +58,14 @@ test("session.set", () => {
});
});

test("session.setFlash", () => {
test("req.session.setFlash", () => {
return new Promise(done => {
const handler = (req, res, session) => {
session.setFlash("state", "dfsafsalfk21lkf12lkf21");
expect(session.get("state")).toMatchInlineSnapshot(
const handler = req => {
req.session.setFlash("state", "dfsafsalfk21lkf12lkf21");
expect(req.session.get("state")).toMatchInlineSnapshot(
`"dfsafsalfk21lkf12lkf21"`
);
expect(session.get("state")).toMatchInlineSnapshot(`undefined`);
expect(req.session.get("state")).toMatchInlineSnapshot(`undefined`);
done();
};
const wrappedHandler = withIronSession(handler, { password });
Expand All @@ -78,10 +78,10 @@ test("session.setFlash", () => {
});
});

test("session.save creates a seal and stores it in a cookie", () => {
test("req.session.save creates a seal and stores it in a cookie", () => {
return new Promise(done => {
const handler = async (req, res, session) => {
await session.save();
const handler = async (req, res) => {
await req.session.save();
const headerName = res.setHeader.mock.calls[0][0];
expect(headerName).toMatchInlineSnapshot(`"set-cookie"`);

Expand Down Expand Up @@ -116,8 +116,8 @@ test("session.save creates a seal and stores it in a cookie", () => {

test("ironStore(handler, {password}) with existing session", async () => {
return new Promise(done => {
const handler = (req, res, session) => {
expect(session.get()).toMatchInlineSnapshot(`
const handler = req => {
expect(req.session.get()).toMatchInlineSnapshot(`
Object {
"user": Object {
"id": 3,
Expand All @@ -141,8 +141,8 @@ Object {

test("When ttl is 0, maxAge have a specific value", () => {
return new Promise(done => {
const handler = async (req, res, session) => {
await session.save();
const handler = async (req, res) => {
await req.session.save();
const headerValue = res.setHeader.mock.calls[0][1];
const cookie = headerValue[0];
const maxAgeParam = cookie.split(";")[1];
Expand All @@ -161,10 +161,10 @@ test("When ttl is 0, maxAge have a specific value", () => {
});
});

test("session.destroy", () => {
test("req.session.destroy", () => {
return new Promise(done => {
const handler = async (req, res, session) => {
session.destroy();
const handler = async (req, res) => {
req.session.destroy();
expect(res.setHeader.mock.calls[0]).toMatchInlineSnapshot(`
Array [
"set-cookie",
Expand All @@ -186,7 +186,3 @@ Array [
);
});
});

// Maybe TODO: warn on no session usage
// Maybe TODO: warn when session saved after end
// Maybe TODO: warn when session not saved after set and req ended

0 comments on commit a58cad5

Please sign in to comment.