Closed FelixZY closed 1 year ago
Hm, I think I got it by defining my middleware in [[...next_rest_framework]].ts
:
export default defineCatchAllHandler({
middleware({ req, res }) {
// Cache requests
// https://vercel.com/docs/concepts/functions/serverless-functions/edge-caching#stale-while-revalidate
if (req.method === "GET") {
res.setHeader("Cache-Control", "s-maxage=3600, stale-while-revalidate");
}
return {};
},
});
However, I have so far been unsuccessful in splitting the middleware into a separate file due to typescript complaints. What type should I use when moving middleware to a separate function? I'm guessing something like
export function authenticated(): Middleware<{}> {
return async ({ req, res }) => {
const token = await getToken({ req });
if (!token) {
res.status(401).end();
}
return {};
}
}
but have so far not gotten this to work:
Argument of type '{ GET: { output: { status: number; contentType: "application/json"; schema: ZodVoid; }[]; middleware: Middleware<{}>; handler({ res }: { req: TypedNextApiRequest<yup.InferType<T>, yup.InferType<T>>; res: TypedNextApiResponse<...>; params: Record<...> | Record<...>; }): Promise<...>; }; }' is not assignable to parameter of type 'DefineEndpointsParams<unknown, unknown, { status: number; contentType: "application/json"; schema: ZodVoid; }, {}, unknown, unknown, OutputObject<number, AnyContentTypeWithAutocompleteForMostCommonOnes, any>, ... 26 more ..., unknown>'.
The types of '[ValidMethod.GET].middleware' are incompatible between these types.
Type 'Middleware<{}>' is not assignable to type 'Middleware<{}, { params: Record<string, unknown>; }, TypedNextApiRequest<yup.InferType<T>, yup.InferType<T>>, TypedNextApiResponse<number, "application/json", void>>'.
Type 'TypedNextApiResponse<number, "application/json", void>' is not assignable to type 'NextApiResponse'.
Type 'TypedNextApiResponse<number, "application/json", void>' is not assignable to type 'ServerResponse<IncomingMessage>'.
The types returned by 'setHeader(...)' are incompatible between these types.
Type 'void' is not assignable to type 'ServerResponse<IncomingMessage>'.
Hey, yeah using the global middleware is one way to set the cache headers for all GET requests. Another way would be to do it using Next.js' native Middleware: https://nextjs.org/docs/pages/building-your-application/routing/middleware
About your TypeScript issue, I can see that your middleware function is a function that returns an async function. With your approach it only works if you actually call it when defining the middleware in your API handler to get the correct middleware function. If you don't want to call the function, here's a correct way to do it:
const authenticated: Middleware<{}> = async ({ req, res }) => {
const token = await getToken();
if (!token) {
res.status(401).end();
}
return {};
}
And then you can use it like this:
export default defineCatchAllHandler({
middleware: authenticated
});
@blomqma Hm, that does not seem to work for me:
const authenticated: Middleware<{}> = async ({ req, res }) => {
const token = await getToken({ req });
if (!token) {
res.status(401).end();
}
return {};
};
export default defineEndpoints({
GET: {
output: [
{
status: 204,
contentType: "application/json",
schema: z.void(),
},
{
status: 401,
contentType: "application/json",
schema: z.void(),
},
],
openApiSpecOverrides: {
summary: "Seed development database",
security: [
{
DeveloperAuth: [],
},
],
} as Partial<OpenAPIObject["paths"][string]["get"]>,
middleware: authenticated,
async handler({ res }) {
await seedDev();
res.setHeader("content-type", "application/json");
res.status(204).json();
},
},
});
gives the same error
Argument of type '{ GET: { output: { status: number; contentType: "application/json"; schema: ZodVoid; }[]; openApiSpecOverrides: Partial<OperationObject | undefined>; middleware: Middleware<...>; handler({ res }: { ...; }): Promise<...>; }; }' is not assignable to parameter of type 'DefineEndpointsParams<unknown, unknown, { status: number; contentType: "application/json"; schema: ZodVoid; }, {}, unknown, unknown, OutputObject<number, AnyContentTypeWithAutocompleteForMostCommonOnes, any>, ... 26 more ..., unknown>'.
The types of '[ValidMethod.GET].middleware' are incompatible between these types.
Type 'Middleware<{}>' is not assignable to type 'Middleware<{}, { params: Record<string, unknown>; }, TypedNextApiRequest<yup.InferType<T>, yup.InferType<T>>, TypedNextApiResponse<number, "application/json", void>>'.
Type 'TypedNextApiResponse<number, "application/json", void>' is not assignable to type 'NextApiResponse'.
Type 'TypedNextApiResponse<number, "application/json", void>' is not assignable to type 'ServerResponse<IncomingMessage>'.
The types returned by 'setHeader(...)' are incompatible between these types.
Type 'void' is not assignable to type 'ServerResponse<IncomingMessage>'.
Sidenote: it would be nice with some built-in typings for the openApiSpecOverrides
. I'm using openapi3-ts
for this currently.
I would like to add global cache headers to all
GET
requests. How can I use middleware to do this?In a more general sense: I'm missing some practical examples of how to implement the different types of middleware (global/route/method).