@@ -272,65 +272,105 @@ public function testInvokesOnRedirectForRedirects()
272272 self ::assertTrue ($ call );
273273 }
274274
275- public function crossOriginRedirectProvider ()
275+ /**
276+ * @testWith ["digest"]
277+ * ["ntlm"]
278+ */
279+ public function testRemoveCurlAuthorizationOptionsOnRedirectCrossHost ($ auth )
276280 {
277- return [
278- ['http://example.com?a=b ' , 'http://test.com/ ' , false ],
279- ['https://example.com?a=b ' , 'https://test.com/ ' , false ],
280- ['http://example.com?a=b ' , 'https://test.com/ ' , false ],
281- ['https://example.com?a=b ' , 'http://test.com/ ' , false ],
282- ['http://example.com?a=b ' , 'http://example.com/ ' , true ],
283- ['https://example.com?a=b ' , 'https://example.com/ ' , true ],
284- ['http://example.com?a=b ' , 'https://example.com/ ' , true ],
285- ['https://example.com?a=b ' , 'http://example.com/ ' , false ],
286- ];
281+ if (!defined ('\CURLOPT_HTTPAUTH ' )) {
282+ self ::markTestSkipped ('ext-curl is required for this test ' );
283+ }
284+
285+ $ mock = new MockHandler ([
286+ new Response (302 , ['Location ' => 'http://test.com ' ]),
287+ static function (RequestInterface $ request , $ options ) {
288+ self ::assertFalse (
289+ isset ($ options ['curl ' ][\CURLOPT_HTTPAUTH ]),
290+ 'curl options still contain CURLOPT_HTTPAUTH entry '
291+ );
292+ self ::assertFalse (
293+ isset ($ options ['curl ' ][\CURLOPT_USERPWD ]),
294+ 'curl options still contain CURLOPT_USERPWD entry '
295+ );
296+ return new Response (200 );
297+ }
298+ ]);
299+ $ handler = HandlerStack::create ($ mock );
300+ $ client = new Client (['handler ' => $ handler ]);
301+ $ client ->get ('http://example.com?a=b ' , ['auth ' => ['testuser ' , 'testpass ' , $ auth ]]);
287302 }
288303
289304 /**
290- * @dataProvider crossOriginRedirectProvider
305+ * @testWith ["digest"]
306+ * ["ntlm"]
291307 */
292- public function testHeadersTreatmentOnRedirect ( $ originalUri , $ targetUri , $ shouldBePresent )
308+ public function testRemoveCurlAuthorizationOptionsOnRedirectCrossPort ( $ auth )
293309 {
294- $ mock = new MockHandler ([
295- new Response (302 , ['Location ' => $ targetUri ]),
296- static function (RequestInterface $ request ) use ($ shouldBePresent ) {
297- self ::assertSame ($ shouldBePresent , $ request ->hasHeader ('Authorization ' ));
298- self ::assertSame ($ shouldBePresent , $ request ->hasHeader ('Cookie ' ));
310+ if (!defined ('\CURLOPT_HTTPAUTH ' )) {
311+ self ::markTestSkipped ('ext-curl is required for this test ' );
312+ }
299313
314+ $ mock = new MockHandler ([
315+ new Response (302 , ['Location ' => 'http://example.com:81/ ' ]),
316+ static function (RequestInterface $ request , $ options ) {
317+ self ::assertFalse (
318+ isset ($ options ['curl ' ][\CURLOPT_HTTPAUTH ]),
319+ 'curl options still contain CURLOPT_HTTPAUTH entry '
320+ );
321+ self ::assertFalse (
322+ isset ($ options ['curl ' ][\CURLOPT_USERPWD ]),
323+ 'curl options still contain CURLOPT_USERPWD entry '
324+ );
300325 return new Response (200 );
301326 }
302327 ]);
303328 $ handler = HandlerStack::create ($ mock );
304329 $ client = new Client (['handler ' => $ handler ]);
305- $ client ->get ($ originalUri , ['auth ' => ['testuser ' , 'testpass ' ], ' headers ' => [ ' Cookie ' => ' foo=bar ' ]]);
330+ $ client ->get (' http://example.com?a=b ' , ['auth ' => ['testuser ' , 'testpass ' , $ auth ]]);
306331 }
307332
308- public function testNotRemoveAuthorizationHeaderOnRedirect ()
333+ /**
334+ * @testWith ["digest"]
335+ * ["ntlm"]
336+ */
337+ public function testRemoveCurlAuthorizationOptionsOnRedirectCrossScheme ($ auth )
309338 {
339+ if (!defined ('\CURLOPT_HTTPAUTH ' )) {
340+ self ::markTestSkipped ('ext-curl is required for this test ' );
341+ }
342+
310343 $ mock = new MockHandler ([
311- new Response (302 , ['Location ' => 'http://example.com/2 ' ]),
312- static function (RequestInterface $ request ) {
313- self ::assertTrue ($ request ->hasHeader ('Authorization ' ));
344+ new Response (302 , ['Location ' => 'http://example.com?a=b ' ]),
345+ static function (RequestInterface $ request , $ options ) {
346+ self ::assertFalse (
347+ isset ($ options ['curl ' ][\CURLOPT_HTTPAUTH ]),
348+ 'curl options still contain CURLOPT_HTTPAUTH entry '
349+ );
350+ self ::assertFalse (
351+ isset ($ options ['curl ' ][\CURLOPT_USERPWD ]),
352+ 'curl options still contain CURLOPT_USERPWD entry '
353+ );
314354 return new Response (200 );
315355 }
316356 ]);
317357 $ handler = HandlerStack::create ($ mock );
318358 $ client = new Client (['handler ' => $ handler ]);
319- $ client ->get ('http ://example.com?a=b ' , ['auth ' => ['testuser ' , 'testpass ' ]]);
359+ $ client ->get ('https ://example.com?a=b ' , ['auth ' => ['testuser ' , 'testpass ' , $ auth ]]);
320360 }
321361
322362 /**
323363 * @testWith ["digest"]
324364 * ["ntlm"]
325365 */
326- public function testRemoveCurlAuthorizationOptionsOnRedirect ($ auth )
366+ public function testRemoveCurlAuthorizationOptionsOnRedirectCrossSchemeSamePort ($ auth )
327367 {
328368 if (!defined ('\CURLOPT_HTTPAUTH ' )) {
329369 self ::markTestSkipped ('ext-curl is required for this test ' );
330370 }
331371
332372 $ mock = new MockHandler ([
333- new Response (302 , ['Location ' => 'http://test .com ' ]),
373+ new Response (302 , ['Location ' => 'http://example .com:80?a=b ' ]),
334374 static function (RequestInterface $ request , $ options ) {
335375 self ::assertFalse (
336376 isset ($ options ['curl ' ][\CURLOPT_HTTPAUTH ]),
@@ -345,7 +385,7 @@ static function (RequestInterface $request, $options) {
345385 ]);
346386 $ handler = HandlerStack::create ($ mock );
347387 $ client = new Client (['handler ' => $ handler ]);
348- $ client ->get ('http ://example.com?a=b ' , ['auth ' => ['testuser ' , 'testpass ' , $ auth ]]);
388+ $ client ->get ('https ://example.com?a=b ' , ['auth ' => ['testuser ' , 'testpass ' , $ auth ]]);
349389 }
350390
351391 /**
@@ -377,6 +417,61 @@ static function (RequestInterface $request, $options) {
377417 $ client ->get ('http://example.com?a=b ' , ['auth ' => ['testuser ' , 'testpass ' , $ auth ]]);
378418 }
379419
420+ public function crossOriginRedirectProvider ()
421+ {
422+ return [
423+ ['http://example.com/123 ' , 'http://example.com/ ' , false ],
424+ ['http://example.com/123 ' , 'http://example.com:80/ ' , false ],
425+ ['http://example.com:80/123 ' , 'http://example.com/ ' , false ],
426+ ['http://example.com:80/123 ' , 'http://example.com:80/ ' , false ],
427+ ['http://example.com/123 ' , 'https://example.com/ ' , true ],
428+ ['http://example.com/123 ' , 'http://www.example.com/ ' , true ],
429+ ['http://example.com/123 ' , 'http://example.com:81/ ' , true ],
430+ ['http://example.com:80/123 ' , 'http://example.com:81/ ' , true ],
431+ ['https://example.com/123 ' , 'https://example.com/ ' , false ],
432+ ['https://example.com/123 ' , 'https://example.com:443/ ' , false ],
433+ ['https://example.com:443/123 ' , 'https://example.com/ ' , false ],
434+ ['https://example.com:443/123 ' , 'https://example.com:443/ ' , false ],
435+ ['https://example.com/123 ' , 'http://example.com/ ' , true ],
436+ ['https://example.com/123 ' , 'https://www.example.com/ ' , true ],
437+ ['https://example.com/123 ' , 'https://example.com:444/ ' , true ],
438+ ['https://example.com:443/123 ' , 'https://example.com:444/ ' , true ],
439+ ];
440+ }
441+
442+ /**
443+ * @dataProvider crossOriginRedirectProvider
444+ */
445+ public function testHeadersTreatmentOnRedirect ($ originalUri , $ targetUri , $ isCrossOrigin )
446+ {
447+ $ mock = new MockHandler ([
448+ new Response (302 , ['Location ' => $ targetUri ]),
449+ static function (RequestInterface $ request ) use ($ isCrossOrigin ) {
450+ self ::assertSame (!$ isCrossOrigin , $ request ->hasHeader ('Authorization ' ));
451+ self ::assertSame (!$ isCrossOrigin , $ request ->hasHeader ('Cookie ' ));
452+
453+ return new Response (200 );
454+ }
455+ ]);
456+ $ handler = HandlerStack::create ($ mock );
457+ $ client = new Client (['handler ' => $ handler ]);
458+ $ client ->get ($ originalUri , ['auth ' => ['testuser ' , 'testpass ' ], 'headers ' => ['Cookie ' => 'foo=bar ' ]]);
459+ }
460+
461+ public function testNotRemoveAuthorizationHeaderOnRedirect ()
462+ {
463+ $ mock = new MockHandler ([
464+ new Response (302 , ['Location ' => 'http://example.com/2 ' ]),
465+ static function (RequestInterface $ request ) {
466+ self ::assertTrue ($ request ->hasHeader ('Authorization ' ));
467+ return new Response (200 );
468+ }
469+ ]);
470+ $ handler = HandlerStack::create ($ mock );
471+ $ client = new Client (['handler ' => $ handler ]);
472+ $ client ->get ('http://example.com?a=b ' , ['auth ' => ['testuser ' , 'testpass ' ]]);
473+ }
474+
380475 /**
381476 * Verifies how RedirectMiddleware::modifyRequest() modifies the method and body of a request issued when
382477 * encountering a redirect response.
0 commit comments