diff --git a/src/handlers/auth.ts b/src/handlers/auth.ts index 2d2bcafa3..26919b61c 100644 --- a/src/handlers/auth.ts +++ b/src/handlers/auth.ts @@ -6,6 +6,7 @@ import { HandleCallback } from './callback'; import { HandleProfile } from './profile'; import { HandlerError } from '../utils/errors'; import { AppRouteHandlerFn, AppRouteHandlerFnContext, Handler } from './router-helpers'; +import { isRequest } from '../utils/req-helpers'; /** * If you want to add some custom behavior to the default auth handlers, you can pass in custom handlers for @@ -183,7 +184,7 @@ export default function handlerFactory({ const pageRouteHandler = pageRouteHandlerFactory(customHandlers, onError as PageRouterOnError); return (req: NextRequest | NextApiRequest, resOrCtx: NextApiResponse | AppRouteHandlerFnContext) => { - if ('params' in resOrCtx) { + if (isRequest(req)) { return appRouteHandler(req as NextRequest, resOrCtx as AppRouteHandlerFnContext); } return pageRouteHandler(req as NextApiRequest, resOrCtx as NextApiResponse); diff --git a/src/handlers/router-helpers.ts b/src/handlers/router-helpers.ts index 39edf0aed..ff36aa671 100644 --- a/src/handlers/router-helpers.ts +++ b/src/handlers/router-helpers.ts @@ -1,5 +1,6 @@ import { NextRequest } from 'next/server'; import { NextApiRequest, NextApiResponse } from 'next'; +import { isRequest } from '../utils/req-helpers'; export type AppRouteHandlerFnContext = { params: Record; @@ -65,16 +66,18 @@ export const getHandler = resOrCtx: NextApiResponse | AppRouteHandlerFnContext, options?: Opts ) => { - if (reqOrOptions instanceof Request) { - return appRouteHandler(reqOrOptions, resOrCtx as AppRouteHandlerFnContext, options); + if (isRequest(reqOrOptions)) { + return appRouteHandler(reqOrOptions as NextRequest, resOrCtx as AppRouteHandlerFnContext, options); } if ('socket' in reqOrOptions) { return pageRouteHandler(reqOrOptions as NextApiRequest, resOrCtx as NextApiResponse, options); } return (req: NextApiRequest | NextRequest, resOrCtxInner: NextApiResponse | AppRouteHandlerFnContext) => { - const opts = typeof reqOrOptions === 'function' ? (reqOrOptions as OptionsProvider)(req) : reqOrOptions; + const opts = ( + typeof reqOrOptions === 'function' ? (reqOrOptions as OptionsProvider)(req) : reqOrOptions + ) as Opts; - if (req instanceof Request) { + if (isRequest(req)) { return appRouteHandler(req as NextRequest, resOrCtxInner as AppRouteHandlerFnContext, opts); } return pageRouteHandler(req as NextApiRequest, resOrCtxInner as NextApiResponse, opts); diff --git a/src/helpers/with-api-auth-required.ts b/src/helpers/with-api-auth-required.ts index b9d7a3c40..d3c6adf11 100644 --- a/src/helpers/with-api-auth-required.ts +++ b/src/helpers/with-api-auth-required.ts @@ -2,6 +2,7 @@ import { NextApiResponse, NextApiRequest, NextApiHandler } from 'next'; import { NextRequest, NextResponse } from 'next/server'; import { get, SessionCache } from '../session'; import { assertReqRes } from '../utils/assert'; +import { isRequest } from '../utils/req-helpers'; /** * This contains `param`s, which is an object containing the dynamic route parameters for the current route. @@ -90,8 +91,11 @@ export default function withApiAuthFactory(sessionCache: SessionCache): WithApiA return (apiRoute: AppRouteHandlerFn | NextApiHandler): any => (req: NextRequest | NextApiRequest, resOrParams: AppRouteHandlerFnContext | NextApiResponse) => { - if (req instanceof Request) { - return appRouteHandler(apiRoute as AppRouteHandlerFn)(req, resOrParams as AppRouteHandlerFnContext); + if (isRequest(req)) { + return appRouteHandler(apiRoute as AppRouteHandlerFn)( + req as NextRequest, + resOrParams as AppRouteHandlerFnContext + ); } return (pageRouteHandler as WithApiAuthRequiredPageRoute)(apiRoute as NextApiHandler)( req as NextApiRequest, diff --git a/src/session/cache.ts b/src/session/cache.ts index 97409fefa..6bbc4f40c 100644 --- a/src/session/cache.ts +++ b/src/session/cache.ts @@ -13,16 +13,17 @@ import { Auth0NextRequest, Auth0NextResponse } from '../http'; +import { isNextApiRequest, isRequest } from '../utils/req-helpers'; type Req = IncomingMessage | NextRequest | NextApiRequest; type Res = ServerResponse | NextResponse | NextApiResponse; const getAuth0Req = (req: Req) => { - if (typeof Request !== undefined && req instanceof Request) { - return new Auth0NextRequest(req); + if (isRequest(req)) { + return new Auth0NextRequest(req as NextRequest); } - if ('previewData' in req) { - return new Auth0NextApiRequest(req); + if (isNextApiRequest(req)) { + return new Auth0NextApiRequest(req as NextApiRequest); } return new NodeRequest(req as IncomingMessage); }; diff --git a/src/utils/req-helpers.ts b/src/utils/req-helpers.ts new file mode 100644 index 000000000..90bdf52e4 --- /dev/null +++ b/src/utils/req-helpers.ts @@ -0,0 +1,13 @@ +import type { IncomingMessage } from 'http'; +import { NextApiRequest } from 'next'; +import { NextRequest } from 'next/server'; + +type Req = IncomingMessage | NextApiRequest | NextRequest | Request | Record; + +export const isRequest = (req: Req): boolean => { + return req instanceof Request || req.headers instanceof Headers; +}; + +export const isNextApiRequest = (req: Req) => { + return !isRequest(req) && 'query' in req; +}; diff --git a/tests/utils/req-helpers.test.ts b/tests/utils/req-helpers.test.ts new file mode 100644 index 000000000..6900125c3 --- /dev/null +++ b/tests/utils/req-helpers.test.ts @@ -0,0 +1,34 @@ +import { Socket } from 'net'; +import { IncomingMessage } from 'http'; +import { NextRequest } from 'next/server'; +import { isRequest, isNextApiRequest } from '../../src/utils/req-helpers'; + +describe('req-helpers', () => { + const req = new Request(new URL('http://example.com')); + const reqNode16 = new Proxy(req, {}); + const reqNext = new NextRequest(new URL('http://example.com')); + const nodeReq = new IncomingMessage(new Socket()); + class NextApiRequest extends IncomingMessage { + constructor() { + super(new Socket()); + } + query = {}; + } + const nextApiReq = new NextApiRequest(); + + test('#isRequest', () => { + expect(isRequest(req)).toBe(true); + expect(isRequest(reqNode16)).toBe(true); + expect(isRequest(reqNext)).toBe(true); + expect(isRequest(nodeReq)).toBe(false); + expect(isRequest(nextApiReq)).toBe(false); + }); + + test('#isNextApiRequest', () => { + expect(isNextApiRequest(req)).toBe(false); + expect(isNextApiRequest(reqNode16)).toBe(false); + expect(isNextApiRequest(reqNext)).toBe(false); + expect(isNextApiRequest(nodeReq)).toBe(false); + expect(isNextApiRequest(nextApiReq)).toBe(true); + }); +});