Modify request objects within middleware function #31188
-
I'm learning about the new middleware feature in Nextjs 12. One thing I've been unable to figure out is modifying request objects within a middleware. Is this currently possible? For example, If I want to append a custom header to all apis, can I have a middleware that appends this custom header to the request object before it gets to the API? For this use case, the value of the header is within the request object so middleware seems like a good solution. I've tried the following, which doesn't work (I think this approach usually works with
|
Beta Was this translation helpful? Give feedback.
Replies: 25 comments 19 replies
-
this might help u: |
Beta Was this translation helpful? Give feedback.
-
Would also love to know if this is possible. Given the lack of communication I'm guessing it's a no? |
Beta Was this translation helpful? Give feedback.
-
I realised I just submitted the same request here #33199 |
Beta Was this translation helpful? Give feedback.
-
I think the ability to change request headers fits harmoniously into the _middleware. |
Beta Was this translation helpful? Give feedback.
-
I found a workaround, but not at all satisfying: Add the required data to the headers in the middleware, then when in your API route or It would be possible to somehow secure the approach in encrypting/decrypting the header between the middleware and the api/component, but it seems all very scrappy, as an unnecessary header will still be send back to the client... Any plan to allow modifying the request as per the initial suggestion? |
Beta Was this translation helpful? Give feedback.
-
I ended up here from Google after being confused why I couldn't set additional values on the request object. I feel like this would be a standard use case. Could this get more eyes from the team? |
Beta Was this translation helpful? Give feedback.
-
Landed here for the same desire. Please implement a reasonable way to modify the req object via middleware on api routes. |
Beta Was this translation helpful? Give feedback.
-
Without this feature, we're forced to use a custom server, which we've been trying to avoid. If you can't modify the request, what even is the point of the middleware? |
Beta Was this translation helpful? Give feedback.
-
I agree with the suggestions. I have a use case where I want to apply a header from our nextjs backend to pass to our separate enterprise api. The client should never know this header was added. In other cases I may want to have the header added and then pass it to the backend but also through to the front end for tracking purposes. As a separate question, is there a mechanism to enforce middleware execution order? Having a config to do it would be nice, but I imagine a fallback that probably would work is to name the middleware in alphabetical order. 1-middleware.js |
Beta Was this translation helpful? Give feedback.
-
Commenting here as well for posterity. I want to use the middleware so that I don't have to refetch everything in each If a user is logged in, append it to the context of the request, find the user permissions, add any other data necessary, make any requests needed, then in |
Beta Was this translation helpful? Give feedback.
-
Another hacky work around we ended up doing to set headers on the response. We're using higher order functions to provide additional context to the response object. I imagine you could do this to add locals to the request object too. However, note that this does not make use of next middleware. Here's an example: // utils/cookies.ts
import { NextApiRequest, NextApiResponse } from 'next'
type CookieFn = (...) => void
type NextServerFunction = (
req: NextApiRequest,
res: NextApiResponse
) => Promise<void>
export type NextApiResponseWithCookie = NextApiResponse & { cookie: CookieFn }
type NextServerFunctionWithCookie = (
req: NextApiRequest,
res: NextApiResponseWithCookie
) => Promise<void>
type WithCookiesComposer = (
handler: NextServerFunctionWithCookie
) => NextServerFunction
const cookie = (res, ...) => { // adds cookies to response header }
export const withCookies: WithCookiesComposer = (handler) => (req, res) => {
Object.assign(res, {
cookie: ((...cookieAttributes) => {
cookie(res, ...cookieAttributes)
}) as CookieFn,
})
return handler(req, res as NextApiResponseWithCookie)
} And then in our our api file we can call const hander: NextServerFunctionWithCookie = (res, res) => {
// we have access to cookie here
res.cookie(title: 'my_cookie', value: '123')
}
export default withCookies(handler) |
Beta Was this translation helpful? Give feedback.
-
Looks like this is now available with the latest release? Edit: I just tried out the latest release, and it still doesn't work (despite saying it should). This is what I tried out:
Yet the upstream route had neither the cookie nor the header. |
Beta Was this translation helpful? Give feedback.
-
I use something like this to add device type to header: middleware.ts
pages/index.tsx
|
Beta Was this translation helpful? Give feedback.
-
Any news? I want to add authorization header (from http-only cookie) before api requests and middleware seems good for this 🤔 |
Beta Was this translation helpful? Give feedback.
-
I hate myself for trying to figure out why I couldn't get this working for the last 3 days, then finding this thread. FML. 🤦♂️ Gonna leave my separate discussion (vercel/#8487) open, since it seems this is not a Next.js issue but rather just an implementation oversight in Vercel's edge middleware. Overall, I couldn't agree more that this is one of the biggest things I'd intuitively expect to be able to do with middleware; without it edge middleware feels essentially like writing |
Beta Was this translation helpful? Give feedback.
-
Hi, as I also was not able to add something to the NextRequest object from the middleware.ts file, I was following the docs and example to set up a custom express server. The example seems to be a bit out-of-date as it was missing the port and hostname, but I managed to get it running like this: const express = require("express");
const next = require("next");
const bodyParser = require("body-parser");
const userMiddleware = require("./src/middlewares/express/userMiddleware");
const hostname = "localhost";
const port = parseInt(process.env.PORT, 10) || 3000;
const dev = process.env.NODE_ENV !== "production";
const app = next({ dev, hostname, port });
const handle = app.getRequestHandler();
app.prepare().then(() => {
const server = express();
server.use(bodyParser.urlencoded({ extended: true }));
server.use(bodyParser.json());
server.use("/api/*", userMiddleware);
server.all("*", (req, res) => {
return handle(req, res);
});
server.listen(port, () => {
console.log(`> Ready on http://localhost:${port}`);
});
}); My module.exports = async function userMiddleware(req, res, next) {
req.user = {
id: 123,
email: "..."
};
return next();
}; I also needed to extend the express Request object type in the import { User } from "./src/models";
declare module "next" {
interface NextApiRequest {
user?: {
id: number;
email: string;
};
}
}
// If this file has no import/export statements (i.e. is a script)
// convert it into a module by adding an empty export statement.
export {}; Now, I am able to get the user from the Request object. // Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type { NextApiRequest, NextApiResponse } from "next";
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
console.log(req.user);
return res.status(200).json({ status: "ok" });
} |
Beta Was this translation helpful? Give feedback.
-
I'm also facing the same issue when I try to decrypt my cookie before sending the request to the api. |
Beta Was this translation helpful? Give feedback.
-
Looks like we finally got the feature! There's a bug being addressed, but I'm very happy. |
Beta Was this translation helpful? Give feedback.
-
How can we modify the whole request and not only headers? I need to add the requested file upload then read it's properties on my API route. |
Beta Was this translation helpful? Give feedback.
-
Source: https://vercel.com/templates/next.js/edge-functions-modify-request-header |
Beta Was this translation helpful? Give feedback.
-
@IlirBajrami, @bsord, @anthonyalayo I implemented the request object changes like this, it may not be the safest but still works like charm. It would be interesting to see how you guys ended up implementing this. Do share if you've done it. utils/interceptors.ts
pages/api/hello.ts
|
Beta Was this translation helpful? Give feedback.
-
What should I do if I want to attach an object ? I ended up with the hacky solution, not sure this is the right way to do it
And from api
|
Beta Was this translation helpful? Give feedback.
-
You can try this
|
Beta Was this translation helpful? Give feedback.
-
I just discovered that if you call export async function middleware(req) {
const originResponse = await fetch(req.url, { /* Change whatever you want here */ });
return originResponse; // Or change anything before returning
} Note: I haven't tried it on Next, I'm using a custom framework with the Build Output API. |
Beta Was this translation helpful? Give feedback.
Looks like we finally got the feature!
#41380
There's a bug being addressed, but I'm very happy.