question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Sharing state between middlewares using the context

See original GitHub issue

I’ve created a simple session middleware for oak (https://github.com/domenichelfenstein/oak-sessions) because I couldn’t find anything similar in the oak project itself (maybe I just didn’t get the application state right, but I’d like to think, I did).

For the most part, I’m pretty happy with my middleware. But I’ve encountered one problem:

  • When the user starts a new session (no sessionId created so far), my middleware has to create a new session id and store it in the cookies.
  • But unfortunately, this cookie isn’t available in router handling during the same request. (the context gets altered by my middleware but the context-changes from my middleware aren’t available in the context of the router handling)
  • I was able to solve this by introducing a (application-wide) temp variable in my middleware. But I don’t think this can work when requests get processed in parallel

Is there any pattern or process to share data between two middlewares via the context?

Some code to help:

import { Application, Router } from "https://deno.land/x/oak/mod.ts";
import { Session } from "https://raw.githubusercontent.com/domenichelfenstein/oak-sessions/master/mod.ts";

const session = new Session(() => ({ counter: 1 }));
const router = new Router()
    .get("/", async (context) => {
        // 2. here we want to read the session state by using the context
        const state = await session.getState(context);
        context.response.type = "text/html";
        context.response.body = `Counter: ${state.counter}`;

        await session.storeState(context, { counter: state.counter + 1});
    })

const app = new Application();
// 1. This middleware creates a sessionId and initializes a session state
app.use(session.sessionHandling);
app.use(router.routes());
await app.listen({ port: 8000 });

Without my hacky application-wide variable (inside of Session) this code wouldn’t work during the first request (where the session id isn’t known in the request itself).

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:6

github_iconTop GitHub Comments

1reaction
kitsonkcommented, Jul 27, 2020

The context is the same, trust me.

Why you don’t think it is the same is that .cookies.get() only looks at cookie values in the request and not anything in the response. Because of the support for verified keys, I am not too keen on changing the behaviour, it would make it appear that the cookie is actually part of the request, when it isn’t.

I would simply have the middleware move the session state in and out of the context.state… So something like this:

let sessionId = context.cookies.get(SESSION_ID);
let state;
if (!sessionId) {
  sessionId = // new guid
  context.cookies.set(SESSION_ID, sessionId);
  // init state
}
context.state.session = // get state 
await next();
// whatever other cleanup, persistence, whatever
delete context.state.session;

That way, consumers of your middleware don’t have to even think about it, they will simply use:

context.state.session.whatever
0reactions
domenichelfensteincommented, Jul 29, 2020

Thank you so much @kitsonk!

You helped me get rid of the tempKey. I’ve changed my middleware and the corresponding example based on your suggestion. The result can be found here: https://github.com/domenichelfenstein/oak-sessions

Read more comments on GitHub >

github_iconTop Results From Across the Web

Share Values Between Middlewares - Nicolas Mérouze
Tutorial about contexts when programming web applications in Go with middlewares. Includes a comparison of various context libraries.
Read more >
Why does sharing state via Context only work with my request ...
I've been struggling with sharing state from some middleware. Previously in Golang I've setup a "handler struct" and used functions of the ...
Read more >
Sharing Context (ctx) between middleware and policies (and ...
I need to access to ctx.request.route and ctx.state.user but these are available only in policies (and controllers). I tried to play with the ......
Read more >
Middlewares with react context and hooks - DEV Community ‍ ‍
This middleware saves the current state on the local storage, I'm using for this a small library store2 just to make sure retrocompatibility ......
Read more >
Middleware Function for Reducer in Context API - Medium
With the help of the useReducer hook, actions for saving values into the state can be triggered easily from the components that are...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found