#Pass data from middleware to pages

83 messages · Page 1 of 1 (latest)

shell wraith
#

Is it possible to pass some values from the middleware to pages (app router) as it's frequently done when using Express?
Or is there any solution to avoid performing a task (ie: a db query, headers parsing, ...) after it has already been performed in the middleware?

obsidian violetBOT
#

🔎 This post has been indexed in our web forum and will be seen by search engines so other users can find it outside Discord

🕵️ Your user profile is private by default and won't be visible to users outside Discord, if you want to be visible in the web forum you can add the "Public Profile" role in id:customize

✅ You can mark a message as the answer for your post with Right click -> Apps -> Mark Solution
(if you don't see the option, try refreshing Discord with Ctrl + R)

lean belfry
#

It is possible, however, doing that also leaks the values to client

#

It would be best to make a function on top of the route handler to pass the data

#

#discussions message

shell wraith
lean belfry
#

its best to make a function on top of the route handler to pass the values

shell wraith
# lean belfry yes, but it also leaks it to client

It doesn't seem to leak if I do the following:

const newHeaders = new Headers(request.headers);
newHeaders.set('user', JSON.stringify(user));
return NextResponse.next({ request: { headers: newHeaders } });

... but it looks hackish...

At the same time I don't understand what's the other solution you are suggesting.

lean belfry
#

I’ve tried this

shell wraith
#

I should get it in Response headers in the browser, but right now I'm not getting it..

lean belfry
#

In postman I was able to view the headers

lean belfry
shell wraith
#

are you sure you were enriching the passed request headers and not the response headers?

#

because I tried that before and that actually leaked

lean belfry
#

Wait, I'll get additional info and I'll answer this question after tomorrow!

shell wraith
#

super! thx

#

in the meantime, my screeshot where the value is used in a page.tsx but doesn't appear in the response headers

lean belfry
#

generally speaking, headers should only be values that a client provides

shell wraith
#

I agree, in fact I don't like this approach. But I also don't like having to do the same task in both middleware and pages

#

and I find strange there's no easy way to pass something from middleware to pages/routes, but probably I am not fully understanding the full request/response lifecycle in Next

lean belfry
shell wraith
lean belfry
#

I’ll do when I get time

lean belfry
#

@shell wraith check this #discussions message

#
/**
 * Handles POST requests by parsing the request body and validating it against a schema.
 * @param handler - The handler function to be executed if the request body is valid.
 * @param schema - The schema to validate the request body against.
 * @returns A response after executing the function.
 */
export function routePostHandler<T>( schema: ZodSchema<T>, handler: (request: NextRequest, body : T) => Promise<NextResponse | void>) {
    return async (request: NextRequest) => {
        let body: T;
        try {
            body = await request.json();
        } catch (error) {
            return NextResponse.json({message: "Invalid JSON in request body"}, {status: 400});
        }

        const parsed = schema.safeParse(body);

        if (!parsed.success) {
            return NextResponse.json({message: "Invalid request body", errors: parsed.error.issues}, {status: 400});
        }
        const data = await handler(request, parsed.data);
        return data || NextResponse.json({message: "Internal Server Error"}, {status: 500});
    };
#

Check this, in this, its checking if type is valid. A functionality for passing data can be added into it

#

And it can be used in handler like this

export const POST = routePostHandler<Body>(BodySchema, async (req: NextRequest, body: Body) => {
shell wraith
#

thanks very much for the effort, but I think it doesn't solve my use case

#

my scenario is the following: suppose I'm using middleware to handle db based authentication (ie: in middleware I access the db to get the user, if no user no auth). I would like to have the user available in subsequent routes/pages without the need to access the db again to retrieve it, given I already did it in the middleware. The approach above doesn't seem to solve this issue, if I am not missing something.

lean belfry
shell wraith
#

so you mean not using middleware for auth but delegating to the routes/pages?

#

that would be a solution, probably

#

I don't particularly like it, given there is a centralized place where this could be handled (ie: middleware), but it would work

lean belfry
shell wraith
#

ok, thank you

lean belfry
shell wraith
#

@lean belfry Though I'm thankful for your time and effort, I don't consider it to be a valid answer to my question. The code you provided is a factory function (a HOF, to be more specific), that allows you to standardize the creation of route handlers, but doesn't in any way respond to the initial question of avoiding to perform an operation that has already been performed in the middleware. If that was the approach, a simpler solution, without recurring to HOFs (though maybe more elegant), would be to just extract a function that gets the user from db, in my example, and then use/call it in both routes and in pages (also note that the solution you propose is not applicable to pages).
Would you agree with me that having to hit the db multiple times for rendering a page, if I already hit it once for the same data during the page rendering pipeline, doesn't seem an optimal approach? As I probably wrote above, I'm coming from an Express background, and I think Express is the library that popularized the concept of middleware in the JS world, but don't quote me on that. In Express land it is/was a common pattern to enrich the request object with data collected in the middleware chain. So, for example, if I had a requireAuth middleware, I could safely expect to find the user in the request in a subsequent middleware or route handler, which makes a lot of sense to me. I probably don't know a lot of the magic that goes on behind the scenes in Next.js but I'd like to have an answer to my original question, which I don't seem to be able to find anywhere online.

lean belfry
#

You can wait for an answer then!

shell wraith
#

🙏

shell wraith
#

Pass data from middleware to pages

lean belfry
#

Bump(for him, as I also need a answer)

lean belfry
#

Bump(for him, as I also need a answer)

shell wraith
#

@lean belfry I have not had time to find an answer to this yet, but using React's cache (import { cache } from "react") seems to be an interesting path to investigate (https://youtu.be/N_sUsq_y10U?si=utUC4JCr0ysu6mn-&t=412). It sounds an interesting point to evaluate also in another use-case I have enountered, where I needed the same db data both in a Layout and in its child Page

Best practices for authentication in Modern Next.js and React: Server Components, Server Actions, Middleware.

Docs: https://rc.nextjs.org/docs/app/building-your-application/authentication
Code: https://github.com/vercel-labs/app-router-auth

00:00 Intro
00:25 Forms and Server Actions
00:51 Form validation
01:06 useActionState
01:45 Creating a u...

▶ Play video
covert hearth
#

This video will solve your pro @lean belfry

lean belfry
#

Checking it out now!

#

I don't use authjs, so it didn't help

gray kraken
#

@shell wraith Were you able to find a method that works?

misty loom
#

Probably make another post, this one is already greater than 50 messages and hence isn't very helpful for any future reference

#

Even I have no clue wtf is going on above lol

gray kraken
# misty loom What's your usecase you need help with?

I'm currently working on the dashboard and I plan on checking if the user is currently logged in, I'm able to do so properly and redirect them if not, but the library I'm using returns data that can be needed throughout and instead of having to refetch the data I was hoping to just pass it to the page from the middleware

#

I intended to use unstable_cache but it's unstable & I had an error using it with my library

#

I would create another one but I noticed that a majority of posts like this just get ignored so I figure why not ask 😅

misty loom
#

Essentially the middleware runs on every single request

#

And that's gonna slow your site down

#

A shit ton

#

This is coming from the nextjs devs

gray kraken
#

Maybe sense, would it be better to redirect the user on the server component instead of the middleware?

misty loom
#

The thing we do, is in the middleware just check for the cookie existing, that's it. A quick check. Then in any page which needs auth data you just have a function wrapped in unstable cache and react cache

#

Which you can call

#

Unstable cache will cache the request itself, react cache will make sure the data is cached through render passes so only one request is made

gray kraken
#

Interesting, okay. I'll do that instead. If I decided to use react cache how can I reset it?

#

For example, I don't think I'll need to ever revalidate the data, but say they change their name or profile picture

misty loom
#

You can't like reset it since it's main thing is to make sure if you call a function in multiple components, it's only called once and the rest use that

gray kraken
#

I seen revalidateTag or something but not sure I can set tags with react cache

#

How would you go about revalidating the data if they change their username for example?

misty loom
#

React cache isn't "cache" per say, it just memorizes requests

#

Yes ik it's a dumb thing

gray kraken
#

Yeahh I was gonna use unstable cache, but throughout I had this error:

misty loom
#

Or even better

gray kraken
#

So I need to find an alternative

misty loom
#

#discussions message

misty loom
gray kraken
#

I can't

#

unless I create a new supabase client

#

Should I make a new channel for this?

misty loom
#

Yea