Loading docs/manual/integration.md +24 −10 Original line number Diff line number Diff line Loading @@ -531,16 +531,30 @@ export default fedifyWith(federation)( // More details: https://nextjs.org/docs/app/api-reference/file-conventions/middleware#config-object-optional export const config = { runtime: "nodejs", matcher: [{ matcher: [ { source: "/:path*", has: [ { type: "header", key: "Accept", value: ".*application\\\\/((jrd|activity|ld)\\\\+json|xrd\\\\+xml).*", value: ".*application\\/((jrd|activity|ld)\\+json|xrd\\+xml).*", }, ], }, { source: "/:path*", has: [ { type: "header", key: "content-type", value: ".*application\\/((jrd|activity|ld)\\+json|xrd\\+xml).*", }, ], }, { source: "/.well-known/nodeinfo" }, { source: "/.well-known/x-nodeinfo2" }, ], }], }; ~~~~ Loading packages/cli/src/init.ts +24 −10 Original line number Diff line number Diff line Loading @@ -486,16 +486,30 @@ export default fedifyWith(federation)( // More details: https://nextjs.org/docs/app/api-reference/file-conventions/middleware#config-object-optional export const config = { runtime: "nodejs", matcher: [{ matcher: [ { source: "/:path*", has: [ { type: "header", key: "Accept", value: ".*application\\\\/((jrd|activity|ld)\\\\+json|xrd\\\\+xml).*", value: ".*application\\/((jrd|activity|ld)\\+json|xrd\\+xml).*", }, ], }, { source: "/:path*", has: [ { type: "header", key: "content-type", value: ".*application\\/((jrd|activity|ld)\\+json|xrd\\+xml).*", }, ], }, { source: "/.well-known/nodeinfo" }, { source: "/.well-known/x-nodeinfo2" }, ], }], }; `, }, Loading packages/next/README.md +48 −20 Original line number Diff line number Diff line Loading @@ -37,7 +37,8 @@ export default fedifyWith(federation)(); // This config must be defined on `middleware.ts`. export const config = { runtime: "nodejs", matcher: [{ matcher: [ { source: "/:path*", has: [ { Loading @@ -46,7 +47,20 @@ export const config = { value: ".*application\\/((jrd|activity|ld)\\+json|xrd\\+xml).*", }, ], }], }, { source: "/:path*", has: [ { type: "header", key: "content-type", value: ".*application\\/((jrd|activity|ld)\\+json|xrd\\+xml).*", }, ], }, { source: "/.well-known/nodeinfo" }, { source: "/.well-known/x-nodeinfo2" }, ], }; ~~~~ Loading Loading @@ -108,7 +122,8 @@ type ErrorHandlers = Omit<FederationFetchOptions<unknown>, "contextData">; * // More details: https://nextjs.org/docs/app/api-reference/file-conventions/middleware#config-object-optional. * export const config = { * runtime: "nodejs", * matcher: [{ * matcher: [ * { * source: "/:path*", * has: [ * { Loading @@ -117,7 +132,20 @@ type ErrorHandlers = Omit<FederationFetchOptions<unknown>, "contextData">; * value: ".*application\\/((jrd|activity|ld)\\+json|xrd\\+xml).*", * }, * ], * }], * }, * { * source: "/:path*", * has: [ * { * type: "header", * key: "content-type", * value: ".*application\\/((jrd|activity|ld)\\+json|xrd\\+xml).*", * }, * ], * }, * { source: "/.well-known/nodeinfo" }, * { source: "/.well-known/x-nodeinfo2" }, * ], * }; * ``` */ Loading packages/next/src/index.ts +52 −23 Original line number Diff line number Diff line Loading @@ -51,7 +51,8 @@ type ErrorHandlers = Omit<FederationFetchOptions<unknown>, "contextData">; * // More details: https://nextjs.org/docs/app/api-reference/file-conventions/middleware#config-object-optional. * export const config = { * runtime: "nodejs", * matcher: [{ * matcher: [ * { * source: "/:path*", * has: [ * { Loading @@ -60,7 +61,20 @@ type ErrorHandlers = Omit<FederationFetchOptions<unknown>, "contextData">; * value: ".*application\\/((jrd|activity|ld)\\+json|xrd\\+xml).*", * }, * ], * }], * }, * { * source: "/:path*", * has: [ * { * type: "header", * key: "content-type", * value: ".*application\\/((jrd|activity|ld)\\+json|xrd\\+xml).*", * }, * ], * }, * { source: "/.well-known/nodeinfo" }, * { source: "/.well-known/x-nodeinfo2" }, * ], * }; * ``` */ Loading @@ -70,13 +84,11 @@ export const fedifyWith = <TContextData>( errorHandlers?: Partial<ErrorHandlers>, ) => ( middleware: (request: Request) => unknown = ((_: Request) => { console.log(_); return NextResponse.next(); }), middleware: (request: Request) => unknown = ((_: Request) => NextResponse.next()), ): (request: Request) => unknown => async (request: Request) => { if (hasFederationAcceptHeader(request)) { if (isFederationRequest(request)) { return await integrateFederation( federation, contextDataFactory, Loading @@ -86,20 +98,37 @@ async (request: Request) => { return await middleware(request); }; export const isFederationRequest = (request: Request): boolean => [ hasFederationHeader("accept"), hasFederationHeader("content-type"), isNodeInfoRequest, ].some((f) => f(request)); /** * Check if the request has the "Accept" header matching the federation * Check if the request has the header matching the federation * accept regex. * * @param key The header key to check. * @param request The request to check. * @returns `true` if the request has the "Accept" header matching * @returns `true` if the request has the header matching * the federation accept regex, `false` otherwise. */ export const hasFederationAcceptHeader = (request: Request): boolean => { const acceptHeader = request.headers.get("Accept"); // Check if the Accept header matches the federation accept regex. // If the header is not present, return false. return acceptHeader ? FEDERATION_ACCEPT_REGEX.test(acceptHeader) : false; export const hasFederationHeader = (key: string) => (request: Request): boolean => { const value = request.headers.get(key); return value ? FEDERATION_ACCEPT_REGEX.test(value) : false; }; export const isNodeInfoRequest = (request: Request): boolean => { const url = new URL(request.url); return NODEINFO_PATHS.some((path) => url.pathname.startsWith(path)); }; const NODEINFO_PATHS = [ "/.well-known/nodeinfo", "/.well-known/x-nodeinfo2", ]; const FEDERATION_ACCEPT_REGEX = /.*application\/((jrd|activity|ld)\+json|xrd\+xml).*/; Loading Loading
docs/manual/integration.md +24 −10 Original line number Diff line number Diff line Loading @@ -531,16 +531,30 @@ export default fedifyWith(federation)( // More details: https://nextjs.org/docs/app/api-reference/file-conventions/middleware#config-object-optional export const config = { runtime: "nodejs", matcher: [{ matcher: [ { source: "/:path*", has: [ { type: "header", key: "Accept", value: ".*application\\\\/((jrd|activity|ld)\\\\+json|xrd\\\\+xml).*", value: ".*application\\/((jrd|activity|ld)\\+json|xrd\\+xml).*", }, ], }, { source: "/:path*", has: [ { type: "header", key: "content-type", value: ".*application\\/((jrd|activity|ld)\\+json|xrd\\+xml).*", }, ], }, { source: "/.well-known/nodeinfo" }, { source: "/.well-known/x-nodeinfo2" }, ], }], }; ~~~~ Loading
packages/cli/src/init.ts +24 −10 Original line number Diff line number Diff line Loading @@ -486,16 +486,30 @@ export default fedifyWith(federation)( // More details: https://nextjs.org/docs/app/api-reference/file-conventions/middleware#config-object-optional export const config = { runtime: "nodejs", matcher: [{ matcher: [ { source: "/:path*", has: [ { type: "header", key: "Accept", value: ".*application\\\\/((jrd|activity|ld)\\\\+json|xrd\\\\+xml).*", value: ".*application\\/((jrd|activity|ld)\\+json|xrd\\+xml).*", }, ], }, { source: "/:path*", has: [ { type: "header", key: "content-type", value: ".*application\\/((jrd|activity|ld)\\+json|xrd\\+xml).*", }, ], }, { source: "/.well-known/nodeinfo" }, { source: "/.well-known/x-nodeinfo2" }, ], }], }; `, }, Loading
packages/next/README.md +48 −20 Original line number Diff line number Diff line Loading @@ -37,7 +37,8 @@ export default fedifyWith(federation)(); // This config must be defined on `middleware.ts`. export const config = { runtime: "nodejs", matcher: [{ matcher: [ { source: "/:path*", has: [ { Loading @@ -46,7 +47,20 @@ export const config = { value: ".*application\\/((jrd|activity|ld)\\+json|xrd\\+xml).*", }, ], }], }, { source: "/:path*", has: [ { type: "header", key: "content-type", value: ".*application\\/((jrd|activity|ld)\\+json|xrd\\+xml).*", }, ], }, { source: "/.well-known/nodeinfo" }, { source: "/.well-known/x-nodeinfo2" }, ], }; ~~~~ Loading Loading @@ -108,7 +122,8 @@ type ErrorHandlers = Omit<FederationFetchOptions<unknown>, "contextData">; * // More details: https://nextjs.org/docs/app/api-reference/file-conventions/middleware#config-object-optional. * export const config = { * runtime: "nodejs", * matcher: [{ * matcher: [ * { * source: "/:path*", * has: [ * { Loading @@ -117,7 +132,20 @@ type ErrorHandlers = Omit<FederationFetchOptions<unknown>, "contextData">; * value: ".*application\\/((jrd|activity|ld)\\+json|xrd\\+xml).*", * }, * ], * }], * }, * { * source: "/:path*", * has: [ * { * type: "header", * key: "content-type", * value: ".*application\\/((jrd|activity|ld)\\+json|xrd\\+xml).*", * }, * ], * }, * { source: "/.well-known/nodeinfo" }, * { source: "/.well-known/x-nodeinfo2" }, * ], * }; * ``` */ Loading
packages/next/src/index.ts +52 −23 Original line number Diff line number Diff line Loading @@ -51,7 +51,8 @@ type ErrorHandlers = Omit<FederationFetchOptions<unknown>, "contextData">; * // More details: https://nextjs.org/docs/app/api-reference/file-conventions/middleware#config-object-optional. * export const config = { * runtime: "nodejs", * matcher: [{ * matcher: [ * { * source: "/:path*", * has: [ * { Loading @@ -60,7 +61,20 @@ type ErrorHandlers = Omit<FederationFetchOptions<unknown>, "contextData">; * value: ".*application\\/((jrd|activity|ld)\\+json|xrd\\+xml).*", * }, * ], * }], * }, * { * source: "/:path*", * has: [ * { * type: "header", * key: "content-type", * value: ".*application\\/((jrd|activity|ld)\\+json|xrd\\+xml).*", * }, * ], * }, * { source: "/.well-known/nodeinfo" }, * { source: "/.well-known/x-nodeinfo2" }, * ], * }; * ``` */ Loading @@ -70,13 +84,11 @@ export const fedifyWith = <TContextData>( errorHandlers?: Partial<ErrorHandlers>, ) => ( middleware: (request: Request) => unknown = ((_: Request) => { console.log(_); return NextResponse.next(); }), middleware: (request: Request) => unknown = ((_: Request) => NextResponse.next()), ): (request: Request) => unknown => async (request: Request) => { if (hasFederationAcceptHeader(request)) { if (isFederationRequest(request)) { return await integrateFederation( federation, contextDataFactory, Loading @@ -86,20 +98,37 @@ async (request: Request) => { return await middleware(request); }; export const isFederationRequest = (request: Request): boolean => [ hasFederationHeader("accept"), hasFederationHeader("content-type"), isNodeInfoRequest, ].some((f) => f(request)); /** * Check if the request has the "Accept" header matching the federation * Check if the request has the header matching the federation * accept regex. * * @param key The header key to check. * @param request The request to check. * @returns `true` if the request has the "Accept" header matching * @returns `true` if the request has the header matching * the federation accept regex, `false` otherwise. */ export const hasFederationAcceptHeader = (request: Request): boolean => { const acceptHeader = request.headers.get("Accept"); // Check if the Accept header matches the federation accept regex. // If the header is not present, return false. return acceptHeader ? FEDERATION_ACCEPT_REGEX.test(acceptHeader) : false; export const hasFederationHeader = (key: string) => (request: Request): boolean => { const value = request.headers.get(key); return value ? FEDERATION_ACCEPT_REGEX.test(value) : false; }; export const isNodeInfoRequest = (request: Request): boolean => { const url = new URL(request.url); return NODEINFO_PATHS.some((path) => url.pathname.startsWith(path)); }; const NODEINFO_PATHS = [ "/.well-known/nodeinfo", "/.well-known/x-nodeinfo2", ]; const FEDERATION_ACCEPT_REGEX = /.*application\/((jrd|activity|ld)\+json|xrd\+xml).*/; Loading