@@ -560,21 +560,37 @@ export default class Request extends Duplex implements RequestEvents<Request> {
560
560
561
561
static normalizeArguments ( url ?: string | URL , options ?: Options , defaults ?: Defaults ) : NormalizedOptions {
562
562
const rawOptions = options ;
563
+ const searchParameters = options ?. searchParams ;
564
+ const hooks = options ?. hooks ;
563
565
564
566
if ( is . object ( url ) && ! is . urlInstance ( url ) ) {
565
- options = { ...defaults as NormalizedOptions , ...( url as Options ) , ...options } ;
567
+ options = { ...defaults , ...( url as Options ) , ...options } ;
566
568
} else {
567
569
if ( url && options && options . url ) {
568
570
throw new TypeError ( 'The `url` option is mutually exclusive with the `input` argument' ) ;
569
571
}
570
572
571
- options = { ...defaults as NormalizedOptions , ...options } ;
573
+ options = { ...defaults , ...options } ;
572
574
573
575
if ( url ) {
574
576
options . url = url ;
575
577
}
576
578
}
577
579
580
+ // Prevent duplicating default search params & hooks
581
+ if ( searchParameters === undefined ) {
582
+ delete options . searchParams ;
583
+ } else {
584
+ options . searchParams = searchParameters ;
585
+ }
586
+
587
+ if ( hooks === undefined ) {
588
+ delete options . hooks ;
589
+ } else {
590
+ options . hooks = hooks ;
591
+ }
592
+
593
+ // Setting options to `undefined` turns off its functionalities
578
594
if ( rawOptions && defaults ) {
579
595
for ( const key in rawOptions ) {
580
596
// @ts -ignore Dear TypeScript, all object keys are strings (or symbols which are NOT enumerable).
@@ -637,6 +653,28 @@ export default class Request extends Duplex implements RequestEvents<Request> {
637
653
throw new TypeError ( 'Parameter `auth` is deprecated. Use `username` / `password` instead.' ) ;
638
654
}
639
655
656
+ // `options.searchParams`
657
+ if ( options . searchParams ) {
658
+ if ( ! is . string ( options . searchParams ) && ! ( options . searchParams instanceof URLSearchParams ) ) {
659
+ validateSearchParameters ( options . searchParams ) ;
660
+ }
661
+
662
+ options . searchParams = new URLSearchParams ( options . searchParams as Record < string , string > ) ;
663
+
664
+ // `normalizeArguments()` is also used to merge options
665
+ if ( defaults ?. searchParams ) {
666
+ defaults . searchParams . forEach ( ( value , key ) => {
667
+ ( options ! . searchParams as URLSearchParams ) . append ( key , value ) ;
668
+ } ) ;
669
+ }
670
+ } else {
671
+ options . searchParams = defaults ?. searchParams ;
672
+ }
673
+
674
+ // `options.username` & `options.password`
675
+ options . username = options . username ?? '' ;
676
+ options . password = options . password ?? '' ;
677
+
640
678
// `options.prefixUrl` & `options.url`
641
679
if ( options . prefixUrl ) {
642
680
options . prefixUrl = options . prefixUrl . toString ( ) ;
@@ -675,7 +713,7 @@ export default class Request extends Duplex implements RequestEvents<Request> {
675
713
get : ( ) => prefixUrl
676
714
} ) ;
677
715
678
- // Protocol check
716
+ // Support UNIX sockets
679
717
let { protocol} = options . url ;
680
718
681
719
if ( protocol === 'unix:' ) {
@@ -684,23 +722,25 @@ export default class Request extends Duplex implements RequestEvents<Request> {
684
722
options . url = new URL ( `http://unix${ options . url . pathname } ${ options . url . search } ` ) ;
685
723
}
686
724
725
+ // Set search params
726
+ if ( options . searchParams ) {
727
+ options . url . search = options . searchParams . toString ( ) ;
728
+ }
729
+
730
+ // Trigger search params normalization
687
731
if ( options . url . search ) {
688
732
const triggerSearchParameters = '_GOT_INTERNAL_TRIGGER_NORMALIZATION' ;
689
733
690
734
options . url . searchParams . append ( triggerSearchParameters , '' ) ;
691
735
options . url . searchParams . delete ( triggerSearchParameters ) ;
692
736
}
693
737
738
+ // Protocol check
694
739
if ( protocol !== 'http:' && protocol !== 'https:' ) {
695
740
throw new UnsupportedProtocolError ( options as NormalizedOptions ) ;
696
741
}
697
- }
698
742
699
- // `options.username` & `options.password`
700
- options . username = options . username ?? '' ;
701
- options . password = options . password ?? '' ;
702
-
703
- if ( options . url ) {
743
+ // Update `username` & `password`
704
744
options . url . username = options . username ;
705
745
options . url . password = options . password ;
706
746
}
@@ -725,27 +765,6 @@ export default class Request extends Duplex implements RequestEvents<Request> {
725
765
}
726
766
}
727
767
728
- // `options.searchParams`
729
- if ( options . searchParams ) {
730
- if ( ! is . string ( options . searchParams ) && ! ( options . searchParams instanceof URLSearchParams ) ) {
731
- validateSearchParameters ( options . searchParams ) ;
732
- }
733
-
734
- options . searchParams = new URLSearchParams ( options . searchParams as Record < string , string > ) ;
735
-
736
- // `normalizeArguments()` is also used to merge options
737
- const defaultsAsOptions = defaults as Options | undefined ;
738
- if ( defaultsAsOptions && defaultsAsOptions . searchParams instanceof URLSearchParams ) {
739
- defaultsAsOptions . searchParams . forEach ( ( value , key ) => {
740
- ( options ! . searchParams as URLSearchParams ) . append ( key , value ) ;
741
- } ) ;
742
- }
743
-
744
- if ( options . url ) {
745
- options . url . search = options . searchParams . toString ( ) ;
746
- }
747
- }
748
-
749
768
// `options.cache`
750
769
const { cache} = options ;
751
770
if ( cache ) {
@@ -782,7 +801,6 @@ export default class Request extends Duplex implements RequestEvents<Request> {
782
801
}
783
802
784
803
// `options.hooks`
785
- const areHooksUserDefined = options . hooks !== defaults ?. hooks ;
786
804
options . hooks = { ...options . hooks } ;
787
805
788
806
for ( const event of knownHookEvents ) {
@@ -798,7 +816,7 @@ export default class Request extends Duplex implements RequestEvents<Request> {
798
816
}
799
817
}
800
818
801
- if ( defaults && areHooksUserDefined ) {
819
+ if ( defaults ) {
802
820
for ( const event of knownHookEvents ) {
803
821
const defaultHooks = defaults . hooks [ event ] ;
804
822
0 commit comments