11import { createClerkClient } from '@clerk/backend' ;
2- import type { RequestState } from '@clerk/backend/internal' ;
2+ import type { ClerkRequest , RequestState } from '@clerk/backend/internal' ;
33import { AuthStatus , createClerkRequest } from '@clerk/backend/internal' ;
44import { clerkFrontendApiProxy , DEFAULT_PROXY_PATH , stripTrailingSlashes } from '@clerk/backend/proxy' ;
55import { isDevelopmentFromSecretKey } from '@clerk/shared/keys' ;
@@ -51,7 +51,7 @@ export const authenticateRequest = (opts: AuthenticateRequestParams) => {
5151 ...restOptions
5252 } = options || { } ;
5353
54- const clerkRequest = createClerkRequest ( incomingMessageToRequest ( request ) ) ;
54+ const clerkRequest = opts . clerkRequest ?? createClerkRequest ( incomingMessageToRequest ( request ) ) ;
5555 const env = { ...loadApiEnv ( ) , ...loadClientEnv ( ) } ;
5656
5757 const secretKey = secretKeyInput || env . secretKey ;
@@ -163,21 +163,42 @@ export const authenticateAndDecorateRequest = (options: ClerkMiddlewareOptions =
163163 ) ;
164164 }
165165
166+ // Node accepts request targets/methods (`//`, TRACE) the fetch spec cannot represent; reject those instead of 500ing.
167+ let clerkRequest : ClerkRequest ;
168+ try {
169+ clerkRequest = createClerkRequest ( incomingMessageToRequest ( request ) ) ;
170+ } catch {
171+ response . status ( 400 ) . end ( ) ;
172+ return ;
173+ }
174+
166175 const env = { ...loadApiEnv ( ) , ...loadClientEnv ( ) } ;
167176 const publishableKey = options . publishableKey || env . publishableKey ;
168177 const secretKey = options . secretKey || env . secretKey ;
169178
170179 // Handle Frontend API proxy requests early, before authentication
171180 if ( frontendApiProxy ) {
172- const requestUrl = new URL ( request . originalUrl || request . url , `http://${ request . headers . host } ` ) ;
181+ let requestUrl : URL ;
182+ try {
183+ requestUrl = new URL ( request . originalUrl || request . url , `http://${ request . headers . host } ` ) ;
184+ } catch {
185+ response . status ( 400 ) . end ( ) ;
186+ return ;
187+ }
173188 const isEnabled =
174189 typeof frontendApiProxy . enabled === 'function'
175190 ? frontendApiProxy . enabled ( requestUrl )
176191 : frontendApiProxy . enabled ;
177192
178193 if ( isEnabled && ( requestUrl . pathname === proxyPath || requestUrl . pathname . startsWith ( proxyPath + '/' ) ) ) {
179194 // Convert Express request to Fetch API Request
180- const proxyRequest = requestToProxyRequest ( request ) ;
195+ let proxyRequest : Request ;
196+ try {
197+ proxyRequest = requestToProxyRequest ( request ) ;
198+ } catch {
199+ response . status ( 400 ) . end ( ) ;
200+ return ;
201+ }
181202
182203 // Call the core proxy function
183204 const proxyResponse = await clerkFrontendApiProxy ( proxyRequest , {
@@ -220,7 +241,13 @@ export const authenticateAndDecorateRequest = (options: ClerkMiddlewareOptions =
220241 // against the request's public origin (from x-forwarded-* headers).
221242 let resolvedOptions = options ;
222243 if ( frontendApiProxy && ! options . proxyUrl ) {
223- const requestUrl = new URL ( request . originalUrl || request . url , `http://${ request . headers . host } ` ) ;
244+ let requestUrl : URL ;
245+ try {
246+ requestUrl = new URL ( request . originalUrl || request . url , `http://${ request . headers . host } ` ) ;
247+ } catch {
248+ response . status ( 400 ) . end ( ) ;
249+ return ;
250+ }
224251 const isProxyEnabled =
225252 typeof frontendApiProxy . enabled === 'function'
226253 ? frontendApiProxy . enabled ( requestUrl )
@@ -235,6 +262,7 @@ export const authenticateAndDecorateRequest = (options: ClerkMiddlewareOptions =
235262 clerkClient,
236263 request,
237264 options : resolvedOptions ,
265+ clerkRequest,
238266 } ) ;
239267
240268 const err = setResponseHeaders ( requestState , response ) ;
0 commit comments