@@ -175,7 +175,10 @@ export function decodeStream(
175175 return decodeStream ;
176176}
177177
178- type UndiciStreamOptions = Parameters < typeof undici . stream > [ 1 ] ;
178+ type UndiciStreamOptions = Omit <
179+ undici . Dispatcher . RequestOptions < unknown > ,
180+ 'path'
181+ > ;
179182
180183export interface CheerioRequestOptions extends DecodeStreamOptions {
181184 /** The options passed to `undici`'s `stream` method. */
@@ -184,8 +187,6 @@ export interface CheerioRequestOptions extends DecodeStreamOptions {
184187
185188const defaultRequestOptions : UndiciStreamOptions = {
186189 method : 'GET' ,
187- // Allow redirects by default
188- maxRedirections : 5 ,
189190 // Set an Accept header
190191 headers : {
191192 accept : 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' ,
@@ -222,59 +223,67 @@ export async function fromURL(
222223 let undiciStream : Promise < undici . Dispatcher . StreamData < unknown > > | undefined ;
223224
224225 // Add headers if none were supplied.
225- requestOptions . headers ??= defaultRequestOptions . headers ;
226+ const urlObject = typeof url === 'string' ? new URL ( url ) : url ;
227+ const streamOptions = {
228+ headers : defaultRequestOptions . headers ,
229+ path : urlObject . pathname + urlObject . search ,
230+ ...requestOptions ,
231+ } ;
226232
227233 const promise = new Promise < CheerioAPI > ( ( resolve , reject ) => {
228- undiciStream = undici . stream ( url , requestOptions , ( res ) => {
229- if ( res . statusCode < 200 || res . statusCode >= 300 ) {
230- throw new undici . errors . ResponseError (
231- 'Response Error' ,
232- res . statusCode ,
233- {
234- headers : res . headers ,
235- } ,
236- ) ;
237- }
238-
239- const contentTypeHeader = res . headers [ 'content-type' ] ?? 'text/html' ;
240- const mimeType = new MIMEType (
241- Array . isArray ( contentTypeHeader )
242- ? contentTypeHeader [ 0 ]
243- : contentTypeHeader ,
244- ) ;
245-
246- if ( ! mimeType . isHTML ( ) && ! mimeType . isXML ( ) ) {
247- throw new RangeError (
248- `The content-type "${ mimeType . essence } " is neither HTML nor XML.` ,
234+ undiciStream = new undici . Client ( url )
235+ . compose ( undici . interceptors . redirect ( { maxRedirections : 5 } ) )
236+ . stream ( streamOptions , ( res ) => {
237+ if ( res . statusCode < 200 || res . statusCode >= 300 ) {
238+ throw new undici . errors . ResponseError (
239+ 'Response Error' ,
240+ res . statusCode ,
241+ {
242+ headers : res . headers ,
243+ } ,
244+ ) ;
245+ }
246+
247+ const contentTypeHeader = res . headers [ 'content-type' ] ?? 'text/html' ;
248+ const mimeType = new MIMEType (
249+ Array . isArray ( contentTypeHeader )
250+ ? contentTypeHeader [ 0 ]
251+ : contentTypeHeader ,
249252 ) ;
250- }
251-
252- // Forward the charset from the header to the decodeStream.
253- encoding . transportLayerEncodingLabel = mimeType . parameters . get ( 'charset' ) ;
254-
255- /*
256- * If we allow redirects, we will have entries in the history.
257- * The last entry will be the final URL.
258- */
259- const history = (
260- res . context as
261- | {
262- history ?: URL [ ] ;
263- }
264- | undefined
265- ) ?. history ;
266-
267- const opts = {
268- encoding,
269- // Set XML mode based on the MIME type.
270- xmlMode : mimeType . isXML ( ) ,
271- // Set the `baseURL` to the final URL.
272- baseURL : history ? history [ history . length - 1 ] : url ,
273- ...cheerioOptions ,
274- } ;
275-
276- return decodeStream ( opts , ( err , $ ) => ( err ? reject ( err ) : resolve ( $ ) ) ) ;
277- } ) ;
253+
254+ if ( ! mimeType . isHTML ( ) && ! mimeType . isXML ( ) ) {
255+ throw new RangeError (
256+ `The content-type "${ mimeType . essence } " is neither HTML nor XML.` ,
257+ ) ;
258+ }
259+
260+ // Forward the charset from the header to the decodeStream.
261+ encoding . transportLayerEncodingLabel =
262+ mimeType . parameters . get ( 'charset' ) ;
263+
264+ /*
265+ * If we allow redirects, we will have entries in the history.
266+ * The last entry will be the final URL.
267+ */
268+ const history = (
269+ res . context as
270+ | {
271+ history ?: URL [ ] ;
272+ }
273+ | undefined
274+ ) ?. history ;
275+
276+ const opts = {
277+ encoding,
278+ // Set XML mode based on the MIME type.
279+ xmlMode : mimeType . isXML ( ) ,
280+ // Set the `baseURL` to the final URL.
281+ baseURL : history ? history [ history . length - 1 ] : url ,
282+ ...cheerioOptions ,
283+ } ;
284+
285+ return decodeStream ( opts , ( err , $ ) => ( err ? reject ( err ) : resolve ( $ ) ) ) ;
286+ } ) ;
278287 } ) ;
279288
280289 // Let's make sure the request is completed before returning the promise.
0 commit comments