@@ -50,7 +50,10 @@ private static function prepareRequest(?string $method, ?string $url, array $opt
5050 }
5151 $ options ['body ' ] = self ::jsonEncode ($ options ['json ' ]);
5252 unset($ options ['json ' ]);
53- $ options ['headers ' ]['content-type ' ] = $ options ['headers ' ]['content-type ' ] ?? ['application/json ' ];
53+
54+ if (!isset ($ options ['normalized_headers ' ]['content-type ' ])) {
55+ $ options ['normalized_headers ' ]['content-type ' ] = [$ options ['headers ' ][] = 'Content-Type: application/json ' ];
56+ }
5457 }
5558
5659 if (isset ($ options ['body ' ])) {
@@ -61,19 +64,6 @@ private static function prepareRequest(?string $method, ?string $url, array $opt
6164 $ options ['peer_fingerprint ' ] = self ::normalizePeerFingerprint ($ options ['peer_fingerprint ' ]);
6265 }
6366
64- // Compute request headers
65- $ requestHeaders = $ headers = [];
66-
67- foreach ($ options ['headers ' ] as $ name => $ values ) {
68- foreach ($ values as $ value ) {
69- $ requestHeaders [] = $ name .': ' .$ headers [$ name ][] = $ value = (string ) $ value ;
70-
71- if (\strlen ($ value ) !== strcspn ($ value , "\r\n\0" )) {
72- throw new InvalidArgumentException (sprintf ('Invalid header value: CR/LF/NUL found in "%s". ' , $ value ));
73- }
74- }
75- }
76-
7767 // Validate on_progress
7868 if (!\is_callable ($ onProgress = $ options ['on_progress ' ] ?? 'var_dump ' )) {
7969 throw new InvalidArgumentException (sprintf ('Option "on_progress" must be callable, %s given. ' , \is_object ($ onProgress ) ? \get_class ($ onProgress ) : \gettype ($ onProgress )));
@@ -102,15 +92,14 @@ private static function prepareRequest(?string $method, ?string $url, array $opt
10292
10393 if (null !== $ url ) {
10494 // Merge auth with headers
105- if (($ options ['auth_basic ' ] ?? false ) && !($ headers ['authorization ' ] ?? false )) {
106- $ requestHeaders [] = 'authorization: ' . $ headers [ ' authorization ' ][] = 'Basic ' .base64_encode ($ options ['auth_basic ' ]);
95+ if (($ options ['auth_basic ' ] ?? false ) && !($ options [ ' normalized_headers ' ] ['authorization ' ] ?? false )) {
96+ $ options [ ' normalized_headers ' ][ 'authorization ' ] = [ $ options [ ' headers ' ][] = 'Authorization: Basic ' .base64_encode ($ options ['auth_basic ' ])] ;
10797 }
10898 // Merge bearer with headers
109- if (($ options ['auth_bearer ' ] ?? false ) && !($ headers ['authorization ' ] ?? false )) {
110- $ requestHeaders [] = 'authorization: ' . $ headers [ ' authorization ' ][] = 'Bearer ' .$ options ['auth_bearer ' ];
99+ if (($ options ['auth_bearer ' ] ?? false ) && !($ options [ ' normalized_headers ' ] ['authorization ' ] ?? false )) {
100+ $ options [ ' normalized_headers ' ][ 'authorization ' ] = [ $ options [ ' headers ' ][] = 'Authorization: Bearer ' .$ options ['auth_bearer ' ] ];
111101 }
112102
113- $ options ['request_headers ' ] = $ requestHeaders ;
114103 unset($ options ['auth_basic ' ], $ options ['auth_bearer ' ]);
115104
116105 // Parse base URI
@@ -124,7 +113,6 @@ private static function prepareRequest(?string $method, ?string $url, array $opt
124113 }
125114
126115 // Finalize normalization of options
127- $ options ['headers ' ] = $ headers ;
128116 $ options ['http_version ' ] = (string ) ($ options ['http_version ' ] ?? '' ) ?: null ;
129117 $ options ['timeout ' ] = (float ) ($ options ['timeout ' ] ?? ini_get ('default_socket_timeout ' ));
130118
@@ -136,31 +124,38 @@ private static function prepareRequest(?string $method, ?string $url, array $opt
136124 */
137125 private static function mergeDefaultOptions (array $ options , array $ defaultOptions , bool $ allowExtraOptions = false ): array
138126 {
139- unset($ options ['request_headers ' ], $ defaultOptions ['request_headers ' ]);
140-
141- $ options ['headers ' ] = self ::normalizeHeaders ($ options ['headers ' ] ?? []);
127+ $ options ['normalized_headers ' ] = self ::normalizeHeaders ($ options ['headers ' ] ?? []);
142128
143129 if ($ defaultOptions ['headers ' ] ?? false ) {
144- $ options ['headers ' ] += self ::normalizeHeaders ($ defaultOptions ['headers ' ]);
130+ $ options ['normalized_headers ' ] += self ::normalizeHeaders ($ defaultOptions ['headers ' ]);
145131 }
146132
147- if ($ options ['resolve ' ] ?? false ) {
148- $ options ['resolve ' ] = array_change_key_case ($ options ['resolve ' ]);
133+ $ options ['headers ' ] = array_merge (...array_values ($ options ['normalized_headers ' ]) ?: [[]]);
134+
135+ if ($ resolve = $ options ['resolve ' ] ?? false ) {
136+ $ options ['resolve ' ] = [];
137+ foreach ($ resolve as $ k => $ v ) {
138+ $ options ['resolve ' ][substr (self ::parseUrl ('http:// ' .$ k )['authority ' ], 2 )] = (string ) $ v ;
139+ }
149140 }
150141
151142 // Option "query" is never inherited from defaults
152143 $ options ['query ' ] = $ options ['query ' ] ?? [];
153144
154145 foreach ($ defaultOptions as $ k => $ v ) {
155- $ options [$ k ] = $ options [$ k ] ?? $ v ;
146+ if ('normalized_headers ' !== $ k && !isset ($ options [$ k ])) {
147+ $ options [$ k ] = $ v ;
148+ }
156149 }
157150
158151 if (isset ($ defaultOptions ['extra ' ])) {
159152 $ options ['extra ' ] += $ defaultOptions ['extra ' ];
160153 }
161154
162- if ($ defaultOptions ['resolve ' ] ?? false ) {
163- $ options ['resolve ' ] += array_change_key_case ($ defaultOptions ['resolve ' ]);
155+ if ($ resolve = $ defaultOptions ['resolve ' ] ?? false ) {
156+ foreach ($ resolve as $ k => $ v ) {
157+ $ options ['resolve ' ] += [substr (self ::parseUrl ('http:// ' .$ k )['authority ' ], 2 ) => (string ) $ v ];
158+ }
164159 }
165160
166161 if ($ allowExtraOptions || !$ defaultOptions ) {
@@ -169,7 +164,7 @@ private static function mergeDefaultOptions(array $options, array $defaultOption
169164
170165 // Look for unsupported options
171166 foreach ($ options as $ name => $ v ) {
172- if (\array_key_exists ($ name , $ defaultOptions )) {
167+ if (\array_key_exists ($ name , $ defaultOptions ) || ' normalized_headers ' === $ name ) {
173168 continue ;
174169 }
175170
@@ -188,9 +183,9 @@ private static function mergeDefaultOptions(array $options, array $defaultOption
188183 }
189184
190185 /**
191- * Normalizes headers by putting their names as lowercased keys.
192- *
193186 * @return string[][]
187+ *
188+ * @throws InvalidArgumentException When an invalid header is found
194189 */
195190 private static function normalizeHeaders (array $ headers ): array
196191 {
@@ -204,10 +199,15 @@ private static function normalizeHeaders(array $headers): array
204199 $ values = (array ) $ values ;
205200 }
206201
207- $ normalizedHeaders [$ name = strtolower ($ name )] = [];
202+ $ lcName = strtolower ($ name );
203+ $ normalizedHeaders [$ lcName ] = [];
208204
209205 foreach ($ values as $ value ) {
210- $ normalizedHeaders [$ name ][] = $ value ;
206+ $ normalizedHeaders [$ lcName ][] = $ value = $ name .': ' .$ value ;
207+
208+ if (\strlen ($ value ) !== strcspn ($ value , "\r\n\0" )) {
209+ throw new InvalidArgumentException (sprintf ('Invalid header: CR/LF/NUL found in "%s". ' , $ value ));
210+ }
211211 }
212212 }
213213
0 commit comments