@@ -39,6 +39,7 @@ const MFE_FLAG_VALUE = 'vercel-mfe-flag-value';
3939// - with flag enabled middleware will route the request to the zone
4040// This flag informs middleware to ignore the flag function and use this value instead.
4141const MFE_FLAG_VALUE_HEADER = `x-${ MFE_FLAG_VALUE } ` ;
42+ const VERCEL_TOOLBAR_PROXY_BASE_PATH = '/.well-known/vercel-toolbar' ;
4243
4344interface ProxyTarget {
4445 application : string ;
@@ -217,6 +218,16 @@ export class ProxyRequestRouter {
217218 middlewareMfeZone ?: string ;
218219 mfeFlagValue ?: boolean ;
219220 } ) : ProxyTarget | null {
221+ const toolbarTarget = this . checkVercelToolbar ( {
222+ path,
223+ url,
224+ referer,
225+ applications,
226+ } ) ;
227+ if ( toolbarTarget ) {
228+ return toolbarTarget ;
229+ }
230+
220231 for ( const application of Object . values ( applications ) ) {
221232 const target = this . getApplicationTarget ( application ) ;
222233 if ( middlewareMfeZone ) {
@@ -354,6 +365,59 @@ export class ProxyRequestRouter {
354365 } ;
355366 }
356367
368+ checkVercelToolbar ( {
369+ path,
370+ url,
371+ referer = undefined ,
372+ applications,
373+ } : {
374+ path : string ;
375+ url : URL ;
376+ referer ?: string ;
377+ applications : ChildApplication [ ] ;
378+ } ) : ProxyTarget | null {
379+ const isVercelToolbarRequest =
380+ url . pathname === VERCEL_TOOLBAR_PROXY_BASE_PATH ||
381+ url . pathname . startsWith ( `${ VERCEL_TOOLBAR_PROXY_BASE_PATH } /` ) ;
382+ if ( ! isVercelToolbarRequest ) {
383+ return null ;
384+ }
385+
386+ if ( referer ) {
387+ const refererURL = new URL ( referer ) ;
388+ const refererTarget =
389+ this . findMatchingApplication ( {
390+ path : `${ refererURL . pathname } ${ refererURL . search } ` ,
391+ url : refererURL ,
392+ applications,
393+ } ) ?? this . getDefaultHost ( this . config ) ;
394+
395+ if ( refererTarget . isLocal ) {
396+ logger . debug (
397+ ` ${ path } - Routing Vercel Toolbar request to referring application: ${ formatProxyTarget ( refererTarget ) } ` ,
398+ ) ;
399+ return {
400+ ...refererTarget ,
401+ path : `${ url . pathname } ${ url . search } ` ,
402+ } ;
403+ }
404+ }
405+
406+ const localApp = this . getSingleLocalApp ( ) ;
407+ if ( ! localApp ) {
408+ return null ;
409+ }
410+
411+ const target = this . getApplicationTarget ( localApp ) ;
412+ logger . debug (
413+ ` ${ path } - Routing Vercel Toolbar request to only locally running application: ${ formatProxyTarget ( target ) } ` ,
414+ ) ;
415+ return {
416+ ...target ,
417+ path : `${ url . pathname } ${ url . search } ` ,
418+ } ;
419+ }
420+
357421 checkNextSourceMap ( { url } : { url : URL } ) : ProxyTarget | null {
358422 const isSourceMap = pathToRegexp ( '/__nextjs_source-map' ) . test ( url . pathname ) ;
359423 if ( ! isSourceMap ) {
@@ -425,21 +489,32 @@ export class ProxyRequestRouter {
425489
426490 isDefaultAppLocal ( ) : boolean {
427491 const defaultApp = this . config . getDefaultApplication ( ) ;
428- return Boolean (
429- this . localApps . find (
430- ( name ) => name === defaultApp . name || name === defaultApp . packageName ,
431- ) ,
432- ) ;
492+ return this . isApplicationLocal ( defaultApp ) ;
433493 }
434494
435495 getArbitraryLocalApp ( ) {
436496 for ( const application of this . config . getAllApplications ( ) ) {
437- const name = application . name ;
438- if ( this . localApps . includes ( name ) ) {
497+ if ( this . isApplicationLocal ( application ) ) {
439498 return application ;
440499 }
441500 }
442501 }
502+
503+ getSingleLocalApp ( ) : Application | undefined {
504+ const localApplications = this . config
505+ . getAllApplications ( )
506+ . filter ( ( application ) => this . isApplicationLocal ( application ) ) ;
507+
508+ return localApplications . length === 1 ? localApplications [ 0 ] : undefined ;
509+ }
510+
511+ isApplicationLocal ( application : Application ) : boolean {
512+ return Boolean (
513+ this . localApps . find (
514+ ( name ) => name === application . name || name === application . packageName ,
515+ ) ,
516+ ) ;
517+ }
443518}
444519
445520export interface ProxyRequest {
0 commit comments