@@ -11,8 +11,8 @@ import {
1111 AbortError ,
1212 RetryError ,
1313 FetchInit ,
14- SimpleSessionHttp2 ,
1514} from "./core" ;
15+ import { SimpleSessionHttp2 } from "./simple-session" ;
1616import {
1717 FetchExtra ,
1818 handleSignalAndTimeout ,
@@ -27,7 +27,13 @@ import {
2727import { GuardedHeaders } from "./headers" ;
2828import { Request } from "./request" ;
2929import { Response , StreamResponse } from "./response" ;
30- import { arrayify , isRedirectStatus , parseLocation , pipeline } from "./utils" ;
30+ import {
31+ arrayify ,
32+ isRedirectStatus ,
33+ parseLocation ,
34+ pipeline ,
35+ ParsedLocation ,
36+ } from "./utils" ;
3137import { hasGotGoaway } from "./utils-http2" ;
3238
3339const {
@@ -121,6 +127,7 @@ async function fetchImpl(
121127 } ;
122128
123129 let stream : ClientHttp2Stream ;
130+ let shouldCleanupSocket = true ;
124131 try
125132 {
126133 stream = h2session . request ( headersToSend , { endStream } ) ;
@@ -177,7 +184,8 @@ async function fetchImpl(
177184
178185 stream . on ( "close" , guard ( ( ) =>
179186 {
180- socketCleanup ( ) ;
187+ if ( shouldCleanupSocket )
188+ socketCleanup ( ) ;
181189
182190 // We'll get an 'error' event if there actually is an
183191 // error, but not if we got NGHTTP2_NO_ERROR.
@@ -313,8 +321,11 @@ async function fetchImpl(
313321 )
314322 ) ;
315323
324+ const { url : locationUrl , isRelative } =
325+ location as ParsedLocation ;
326+
316327 if ( redirect === "error" )
317- return reject ( makeRedirectionError ( location ) ) ;
328+ return reject ( makeRedirectionError ( locationUrl ) ) ;
318329
319330 // redirect is 'follow'
320331
@@ -323,25 +334,38 @@ async function fetchImpl(
323334 // body). The concept is fundementally broken anyway...
324335 if ( ! endStream )
325336 return reject (
326- makeRedirectionMethodError ( location , method )
337+ makeRedirectionMethodError ( locationUrl , method )
327338 ) ;
328339
329340 if ( ! location )
330341 return reject ( makeIllegalRedirectError ( ) ) ;
331342
332- stream . destroy ( ) ;
333- resolve (
334- fetchImpl (
343+ if ( isRelative )
344+ {
345+ shouldCleanupSocket = false ;
346+ stream . destroy ( ) ;
347+ resolve ( fetchImpl (
335348 session ,
336- request . clone ( location ) ,
337- { signal , onTrailers } ,
349+ request . clone ( locationUrl ) ,
350+ init ,
338351 {
339352 raceConditionedGoaway,
340353 redirected : redirected . concat ( url ) ,
341354 timeoutAt,
342355 }
343- )
344- ) ;
356+ ) ) ;
357+ }
358+ else
359+ {
360+ resolve ( session . newFetch (
361+ request . clone ( locationUrl ) ,
362+ init ,
363+ {
364+ timeoutAt,
365+ redirected : redirected . concat ( url ) ,
366+ }
367+ ) ) ;
368+ }
345369 } ) ) ;
346370 } ) ;
347371
@@ -371,14 +395,16 @@ async function fetchImpl(
371395export function fetch (
372396 session : SimpleSessionHttp2 ,
373397 input : Request ,
374- init ?: Partial < FetchInit >
398+ init ?: Partial < FetchInit > ,
399+ extra ?: FetchExtra
375400)
376401: Promise < Response >
377402{
378- const timeoutAt = void 0 ;
379-
380- const raceConditionedGoaway = new Set < string > ( ) ;
381- const extra = { timeoutAt, redirected : [ ] , raceConditionedGoaway } ;
403+ const http2Extra : FetchExtraHttp2 = {
404+ timeoutAt : extra ?. timeoutAt ,
405+ redirected : extra ?. redirected ?? [ ] ,
406+ raceConditionedGoaway : new Set < string > ( ) ,
407+ } ;
382408
383- return fetchImpl ( session , input , init , extra ) ;
409+ return fetchImpl ( session , input , init , http2Extra ) ;
384410}
0 commit comments