1- import type { Fetch } from '../internal/builtin-types' ;
1+ import type { Fetch , RequestInfo , RequestInit } from '../internal/builtin-types' ;
2+ import { joinURL } from '../internal/utils/url' ;
23
34export type BrowserRoute = {
45 sessionId : string ;
@@ -62,7 +63,7 @@ export function createRoutingFetch(
6263
6364 return async ( input , init ) => {
6465 const request = new Request ( input , init ) ;
65- const response = await routeRequest ( innerFetch , request , apiOrigin , allowed , cache ) ;
66+ const response = await routeRequest ( innerFetch , { input , init , request } , apiOrigin , allowed , cache ) ;
6667 await sniffAndPopulateCache ( response , cache ) ;
6768 return response ;
6869 } ;
@@ -132,29 +133,37 @@ function populateCache(value: unknown, cache: BrowserRouteCache): void {
132133
133134async function routeRequest (
134135 innerFetch : Fetch ,
135- request : Request ,
136+ {
137+ input,
138+ init,
139+ request,
140+ } : {
141+ input : RequestInfo ;
142+ init : RequestInit | undefined ;
143+ request : Request ;
144+ } ,
136145 apiOrigin : string ,
137146 allowed : ReadonlySet < string > ,
138147 cache : BrowserRouteCache ,
139148) : Promise < Response > {
140149 const url = new URL ( request . url ) ;
141150 if ( url . origin !== apiOrigin ) {
142- return innerFetch ( request ) ;
151+ return innerFetch ( input , init ) ;
143152 }
144153
145154 const match = url . pathname . match ( / ^ \/ (?: v \d + \/ ) ? b r o w s e r s \/ ( [ ^ / ] + ) \/ ( [ ^ / ] + ) ( \/ .* ) ? $ / ) ;
146155 if ( ! match ) {
147- return innerFetch ( request ) ;
156+ return innerFetch ( input , init ) ;
148157 }
149158
150159 const sessionId = decodeURIComponent ( match [ 1 ] ?? '' ) ;
151160 const subresource = match [ 2 ] ?? '' ;
152161 if ( ! sessionId || ! allowed . has ( subresource ) ) {
153- return innerFetch ( request ) ;
162+ return innerFetch ( input , init ) ;
154163 }
155164 const route = cache . get ( sessionId ) ;
156165 if ( route === undefined ) {
157- return innerFetch ( request ) ;
166+ return innerFetch ( input , init ) ;
158167 }
159168
160169 const target = new URL ( joinURL ( route . baseURL , `/${ subresource } ${ match [ 3 ] ?? '' } ` ) ) ;
@@ -169,23 +178,57 @@ async function routeRequest(
169178
170179 const headers = new Headers ( request . headers ) ;
171180 headers . delete ( 'authorization' ) ;
181+ return innerFetch ( target . toString ( ) , buildRoutedInit ( request , init , headers ) ) ;
182+ }
183+
184+ function buildRoutedInit (
185+ request : Request ,
186+ originalInit : RequestInit | undefined ,
187+ headers : Headers ,
188+ ) : RequestInit {
172189 const method = request . method . toUpperCase ( ) ;
173- const init : RequestInit = {
190+ const routedInit = {
191+ ...( ( originalInit ?? { } ) as Record < string , unknown > ) ,
174192 method,
175193 headers,
176194 redirect : request . redirect ,
177195 signal : request . signal ,
178- } ;
179- if ( method !== 'GET' && method !== 'HEAD' && request . body ) {
180- init . body = request . body ;
181- init . duplex = 'half' ;
196+ } as RequestInit & Record < string , unknown > ;
197+
198+ delete routedInit [ 'body' ] ;
199+ delete routedInit [ 'duplex' ] ;
200+
201+ if ( method !== 'GET' && method !== 'HEAD' ) {
202+ const body = requestBodyForFetch ( request , originalInit ) ;
203+ if ( body !== undefined ) {
204+ routedInit . body = body ;
205+ }
206+ if ( originalInit ?. duplex !== undefined ) {
207+ routedInit . duplex = originalInit . duplex ;
208+ } else if ( requiresHalfDuplex ( body ) ) {
209+ routedInit . duplex = 'half' ;
210+ }
211+ }
212+
213+ return routedInit ;
214+ }
215+
216+ function requestBodyForFetch (
217+ request : Request ,
218+ originalInit : RequestInit | undefined ,
219+ ) : RequestInit [ 'body' ] | undefined {
220+ if ( originalInit ?. body !== undefined && originalInit . body !== null ) {
221+ return originalInit . body ;
182222 }
183223
184- return innerFetch ( new Request ( target . toString ( ) , init ) ) ;
224+ return request . body ?? undefined ;
185225}
186226
187- function joinURL ( baseURL : string , path : string ) : string {
188- return `${ baseURL . replace ( / \/ + $ / , '' ) } ${ path . startsWith ( '/' ) ? path : `/${ path } ` } ` ;
227+ function requiresHalfDuplex ( body : RequestInit [ 'body' ] | undefined ) : boolean {
228+ return (
229+ ( ( globalThis as any ) . ReadableStream && body instanceof ( globalThis as any ) . ReadableStream ) ||
230+ ( typeof body === 'object' && body !== null && Symbol . asyncIterator in body )
231+ ) ;
189232}
190233
191234function parseJwtFromCdpWsUrl ( cdpWsUrl : string | undefined ) : string | undefined {
0 commit comments