Skip to content

Commit a2b9d08

Browse files
refactor: clean up request handling (#270)
1 parent d52a8d1 commit a2b9d08

File tree

1 file changed

+41
-14
lines changed

1 file changed

+41
-14
lines changed

packages/dev/src/main.ts

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,22 @@ export class NetlifyDev {
178178
this.#staticHandlerAdditionalDirectories = options.staticFiles?.directories ?? []
179179
}
180180

181+
/**
182+
* Runs a request through the Netlify request chain and returns a `Response`
183+
* if there's a match. We must not disturb the incoming request unless we
184+
* know we will be returning a response, so this method takes a read-only
185+
* request that is safe to access (used for matching) and a getter for the
186+
* actual request (used for handling matches).
187+
*
188+
* @param readRequest Read-only version of the request (without a body)
189+
* @param getWriteRequest Getter for the actual request (with a body)
190+
* @param destPath Destination directory for compiled files
191+
* @param options Options object
192+
* @returns
193+
*/
181194
private async handleInEphemeralDirectory(
182-
matchRequest: Request,
183-
getHandleRequest: () => Request,
195+
readRequest: Request,
196+
getWriteRequest: () => Request,
184197
destPath: string,
185198
options: HandleOptions = {},
186199
): Promise<{ response: Response; type: ResponseType } | undefined> {
@@ -190,51 +203,51 @@ export class NetlifyDev {
190203

191204
// 1. Check if the request matches an edge function. Handles edge functions
192205
// with both modes of cache (manual and off) by running them serially.
193-
const edgeFunctionMatch = await this.#edgeFunctionsHandler?.match(matchRequest)
206+
const edgeFunctionMatch = await this.#edgeFunctionsHandler?.match(readRequest)
194207
if (edgeFunctionMatch) {
195208
return {
196-
response: await edgeFunctionMatch.handle(getHandleRequest()),
209+
response: await edgeFunctionMatch.handle(getWriteRequest()),
197210
type: 'edge-function',
198211
}
199212
}
200213

201214
// 2. Check if the request matches a function.
202-
const functionMatch = await this.#functionsHandler?.match(matchRequest, destPath)
215+
const functionMatch = await this.#functionsHandler?.match(readRequest, destPath)
203216
if (functionMatch) {
204217
// If the function prefers static files, check if there is a static match
205218
// and, if so, return that
206219
if (functionMatch.preferStatic) {
207-
const staticMatch = await this.#staticHandler?.match(matchRequest)
220+
const staticMatch = await this.#staticHandler?.match(readRequest)
208221

209222
if (staticMatch) {
210223
const response = await staticMatch.handle()
211224

212-
await this.#headersHandler?.apply(matchRequest, response, options.headersCollector)
225+
await this.#headersHandler?.apply(readRequest, response, options.headersCollector)
213226

214227
return { response, type: 'static' }
215228
}
216229
}
217230

218231
// Let the function handle the request.
219-
return { response: await functionMatch.handle(getHandleRequest()), type: 'function' }
232+
return { response: await functionMatch.handle(getWriteRequest()), type: 'function' }
220233
}
221234

222235
// 3. Check if the request matches a redirect rule.
223-
const redirectMatch = await this.#redirectsHandler?.match(matchRequest)
236+
const redirectMatch = await this.#redirectsHandler?.match(readRequest)
224237
if (redirectMatch) {
225238
// If the redirect rule matches a function, we'll serve it. The exception
226239
// is if the function prefers static files, which in this case means that
227240
// we'll follow the redirect rule.
228241
const functionMatch = await this.#functionsHandler?.match(new Request(redirectMatch.target), destPath)
229242
if (functionMatch && !functionMatch.preferStatic) {
230243
return {
231-
response: await functionMatch.handle(getHandleRequest()),
244+
response: await functionMatch.handle(getWriteRequest()),
232245
type: 'function',
233246
}
234247
}
235248

236249
const response = await this.#redirectsHandler?.handle(
237-
getHandleRequest(),
250+
getWriteRequest(),
238251
redirectMatch,
239252
async (maybeStaticFile: Request) => {
240253
const staticMatch = await this.#staticHandler?.match(maybeStaticFile)
@@ -256,7 +269,7 @@ export class NetlifyDev {
256269
}
257270
}
258271

259-
const { pathname } = new URL(matchRequest.url)
272+
const { pathname } = new URL(readRequest.url)
260273
if (pathname.startsWith('/.netlify/images')) {
261274
this.#logger.error(
262275
`The Netlify Image CDN is currently only supported in the Netlify CLI. Run ${netlifyCommand('npx netlify dev')} to get started.`,
@@ -266,11 +279,11 @@ export class NetlifyDev {
266279
}
267280

268281
// 4. Check if the request matches a static file.
269-
const staticMatch = await this.#staticHandler?.match(matchRequest)
282+
const staticMatch = await this.#staticHandler?.match(readRequest)
270283
if (staticMatch) {
271284
const response = await staticMatch.handle()
272285

273-
await this.#headersHandler?.apply(matchRequest, response, options.headersCollector)
286+
await this.#headersHandler?.apply(readRequest, response, options.headersCollector)
274287

275288
return { response, type: 'static' }
276289
}
@@ -295,12 +308,21 @@ export class NetlifyDev {
295308
return config
296309
}
297310

311+
/**
312+
* Runs a `Request` through the Netlify request chain. If there is a match,
313+
* it returns the resulting `Response` object; if not, it returns `undefined`.
314+
*/
298315
async handle(request: Request, options: HandleOptions = {}) {
299316
const result = await this.handleAndIntrospect(request, options)
300317

301318
return result?.response
302319
}
303320

321+
/**
322+
* Runs a `Request` through the Netlify request chain. If there is a match,
323+
* it returns an object with the resulting `Response` object and information
324+
* about the match; if not, it returns `undefined`.
325+
*/
304326
async handleAndIntrospect(request: Request, options: HandleOptions = {}) {
305327
await fs.mkdir(this.#functionsServePath, { recursive: true })
306328

@@ -318,6 +340,11 @@ export class NetlifyDev {
318340
}
319341
}
320342

343+
/**
344+
* Runs a Node.js `IncomingMessage` through the Netlify request chain. If
345+
* there is a match, it returns an object with the resulting `Response`
346+
* object and information about the match; if not, it returns `undefined`.
347+
*/
321348
async handleAndIntrospectNodeRequest(request: IncomingMessage, options: HandleOptions = {}) {
322349
await fs.mkdir(this.#functionsServePath, { recursive: true })
323350

0 commit comments

Comments
 (0)