@@ -82,12 +82,6 @@ export interface Features {
8282 enabled ?: boolean
8383 }
8484
85- /**
86- * If your local development setup has its own HTTP server (e.g. Vite), set
87- * its address here.
88- */
89- serverAddress ?: string
90-
9185 /**
9286 * Configuration options for serving static files.
9387 */
@@ -107,6 +101,12 @@ interface NetlifyDevOptions extends Features {
107101 apiToken ?: string
108102 logger ?: Logger
109103 projectRoot ?: string
104+
105+ /**
106+ * If your local development setup has its own HTTP server (e.g. Vite), set
107+ * its address here.
108+ */
109+ serverAddress ?: string | null
110110}
111111
112112const notFoundHandler = async ( ) => new Response ( 'Not found' , { status : 404 } )
@@ -121,6 +121,13 @@ interface HandleOptions {
121121 * {@link } https://docs.netlify.com/routing/headers/
122122 */
123123 headersCollector ?: HeadersCollector
124+
125+ /**
126+ * If your local development setup has its own HTTP server (e.g. Vite), you
127+ * can supply its address here. It will override any value defined in the
128+ * top-level `serverAddress` setting.
129+ */
130+ serverAddress ?: string
124131}
125132
126133export type ResponseType = 'edge-function' | 'function' | 'image' | 'redirect' | 'static'
@@ -149,7 +156,7 @@ export class NetlifyDev {
149156 #logger: Logger
150157 #projectRoot: string
151158 #redirectsHandler?: RedirectsHandler
152- #server ?: string | HTTPServer
159+ #serverAddress ?: string | null
153160 #siteID?: string
154161 #staticHandler?: StaticHandler
155162 #staticHandlerAdditionalDirectories: string [ ]
@@ -178,11 +185,23 @@ export class NetlifyDev {
178185 }
179186 this . #functionsServePath = path . join ( projectRoot , '.netlify' , 'functions-serve' )
180187 this . #logger = options . logger ?? globalThis . console
181- this . #server = options . serverAddress
188+ this . #serverAddress = options . serverAddress
182189 this . #projectRoot = projectRoot
183190 this . #staticHandlerAdditionalDirectories = options . staticFiles ?. directories ?? [ ]
184191 }
185192
193+ private getServerAddress ( requestServerAddress ?: string ) {
194+ if ( requestServerAddress ) {
195+ return requestServerAddress
196+ }
197+
198+ if ( typeof this . #serverAddress === 'string' ) {
199+ return this . #serverAddress
200+ }
201+
202+ throw new Error ( 'Server address is not defined' )
203+ }
204+
186205 /**
187206 * Runs a request through the Netlify request chain and returns a `Response`
188207 * if there's a match. We must not disturb the incoming request unless we
@@ -202,6 +221,8 @@ export class NetlifyDev {
202221 destPath : string ,
203222 options : HandleOptions = { } ,
204223 ) : Promise < { response : Response ; type : ResponseType } | undefined > {
224+ const serverAddress = this . getServerAddress ( options . serverAddress )
225+
205226 // Try to match the request against the different steps in our request chain.
206227 //
207228 // https://docs.netlify.com/platform/request-chain/
@@ -211,15 +232,15 @@ export class NetlifyDev {
211232 const edgeFunctionMatch = await this . #edgeFunctionsHandler?. match ( readRequest )
212233 if ( edgeFunctionMatch ) {
213234 return {
214- response : await edgeFunctionMatch . handle ( getWriteRequest ( ) ) ,
235+ response : await edgeFunctionMatch . handle ( getWriteRequest ( ) , serverAddress ) ,
215236 type : 'edge-function' ,
216237 }
217238 }
218239
219240 // 2. Check if the request matches an image.
220241 const imageMatch = this . #imageHandler?. match ( readRequest )
221242 if ( imageMatch ) {
222- const response = await imageMatch . handle ( )
243+ const response = await imageMatch . handle ( serverAddress )
223244 return { response, type : 'image' }
224245 }
225246
@@ -251,7 +272,7 @@ export class NetlifyDev {
251272 // If the redirect rule matches Image CDN, we'll serve it.
252273 const imageMatch = this . #imageHandler?. match ( redirectRequest )
253274 if ( imageMatch ) {
254- const response = await imageMatch . handle ( )
275+ const response = await imageMatch . handle ( serverAddress )
255276 return { response, type : 'image' }
256277 }
257278
@@ -403,9 +424,9 @@ export class NetlifyDev {
403424 // If a custom server has been provided, use it. If not, we must stand up
404425 // a new one, since it's required for communication with edge functions
405426 // and local images support for Image CDN.
406- if ( typeof this . #server === 'string' ) {
407- serverAddress = this . #server
408- } else if ( this . #features. edgeFunctions || this . #features. images ) {
427+ if ( typeof this . #serverAddress === 'string' ) {
428+ serverAddress = this . #serverAddress
429+ } else if ( this . #serverAddress !== null && ( this . # features. edgeFunctions || this . #features. images ) ) {
409430 const passthroughServer = new HTTPServer ( async ( req ) => {
410431 const res = await this . handle ( req )
411432
@@ -415,6 +436,7 @@ export class NetlifyDev {
415436 this . #cleanupJobs. push ( ( ) => passthroughServer . stop ( ) )
416437
417438 serverAddress = await passthroughServer . start ( )
439+ this . #serverAddress = serverAddress
418440 }
419441
420442 let envVariables : Record < string , InjectedEnvironmentVariable > = { }
@@ -430,7 +452,7 @@ export class NetlifyDev {
430452 } )
431453 }
432454
433- if ( this . #features. edgeFunctions && serverAddress !== undefined ) {
455+ if ( this . #features. edgeFunctions ) {
434456 const env = Object . entries ( envVariables ) . reduce < Record < string , string > > ( ( acc , [ key , variable ] ) => {
435457 if (
436458 variable . usedSource === 'account' ||
@@ -454,7 +476,6 @@ export class NetlifyDev {
454476 env,
455477 geolocation : mockLocation ,
456478 logger : this . #logger,
457- originServerAddress : serverAddress ,
458479 siteID,
459480 siteName : config ?. siteInfo . name ,
460481 } )
@@ -511,7 +532,6 @@ export class NetlifyDev {
511532 this . #imageHandler = new ImageHandler ( {
512533 imagesConfig : this . #config?. config . images ,
513534 logger : this . #logger,
514- originServerAddress : serverAddress ,
515535 } )
516536 }
517537
0 commit comments