feature #30556 [HttpClient] Allow to pass user/pw as an array (dunglas)
This PR was merged into the 4.3-dev branch.
Discussion
----------
[HttpClient] Allow to pass user/pw as an array
| Q | A
| ------------- | ---
| Branch? | master <!-- see below -->
| Bug fix? | no
| New feature? | yes<!-- don't forget to update src/**/CHANGELOG.md files -->
| BC breaks? | no <!-- see https://symfony.com/bc -->
| Deprecations? | no <!-- don't forget to update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Tests pass? | yes <!-- please add some, will be required by reviewers -->
| Fixed tickets | n/a <!-- #-prefixed issue number(s), if any -->
| License | MIT
| Doc PR | n/a
Makes the API a bit more "PHPish".
Commits
-------
8d5096a638
[HttpClient] Allow to pass user/pw as an array
This commit is contained in:
commit
8af6395fa8
@ -71,8 +71,17 @@ trait HttpClientTrait
|
||||
throw new InvalidArgumentException(sprintf('Option "on_progress" must be callable, %s given.', \is_object($onProgress) ? \get_class($onProgress) : \gettype($onProgress)));
|
||||
}
|
||||
|
||||
if (\is_array($options['auth_basic'] ?? null)) {
|
||||
$count = \count($options['auth_basic']);
|
||||
if ($count <= 0 || $count > 2) {
|
||||
throw new InvalidArgumentException(sprintf('Option "auth_basic" must contain 1 or 2 elements, %s given.', $count));
|
||||
}
|
||||
|
||||
$options['auth_basic'] = implode(':', $options['auth_basic']);
|
||||
}
|
||||
|
||||
if (!\is_string($options['auth_basic'] ?? '')) {
|
||||
throw new InvalidArgumentException(sprintf('Option "auth_basic" must be string, %s given.', \gettype($options['auth_basic'])));
|
||||
throw new InvalidArgumentException(sprintf('Option "auth_basic" must be string or an array, %s given.', \gettype($options['auth_basic'])));
|
||||
}
|
||||
|
||||
if (!\is_string($options['auth_bearer'] ?? '')) {
|
||||
|
@ -34,9 +34,12 @@ class HttpOptions
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function setAuthBasic(string $userinfo)
|
||||
public function setAuthBasic(string $user, string $password = '')
|
||||
{
|
||||
$this->options['auth'] = $userinfo;
|
||||
$this->options['auth_basic'] = $user;
|
||||
if ('' !== $password) {
|
||||
$this->options['auth_basic'] .= ':'.$password;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -185,8 +185,25 @@ class HttpClientTraitTest extends TestCase
|
||||
* @expectedException \Symfony\Component\HttpClient\Exception\InvalidArgumentException
|
||||
* @expectedExceptionMessage Define either the "auth_basic" or the "auth_bearer" option, setting both is not supported.
|
||||
*/
|
||||
public function testSetBasicAndBearerOption()
|
||||
public function testSetAuthBasicAndBearerOptions()
|
||||
{
|
||||
self::prepareRequest('POST', 'http://example.com', ['auth_bearer' => 'foo', 'auth_basic' => 'foo:bar'], HttpClientInterface::OPTIONS_DEFAULTS);
|
||||
}
|
||||
|
||||
public function providePrepareAuthBasic()
|
||||
{
|
||||
yield ['foo:bar', 'Zm9vOmJhcg=='];
|
||||
yield [['foo', 'bar'], 'Zm9vOmJhcg=='];
|
||||
yield ['foo', 'Zm9v'];
|
||||
yield [['foo'], 'Zm9v'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providePrepareAuthBasic
|
||||
*/
|
||||
public function testPrepareAuthBasic($arg, $result)
|
||||
{
|
||||
[, $options] = $this->prepareRequest('POST', 'http://example.com', ['auth_basic' => $arg], HttpClientInterface::OPTIONS_DEFAULTS);
|
||||
$this->assertSame('Basic '.$result, $options['headers']['authorization'][0]);
|
||||
}
|
||||
}
|
||||
|
37
src/Symfony/Component/HttpClient/Tests/HttpOptionsTest.php
Normal file
37
src/Symfony/Component/HttpClient/Tests/HttpOptionsTest.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpClient\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\HttpClient\HttpOptions;
|
||||
|
||||
/**
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class HttpOptionsTest extends TestCase
|
||||
{
|
||||
public function provideSetAuth()
|
||||
{
|
||||
yield ['user:password', 'user', 'password'];
|
||||
yield ['user:password', 'user:password'];
|
||||
yield ['user', 'user'];
|
||||
yield ['user:0', 'user', '0'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideSetAuth
|
||||
*/
|
||||
public function testSetAuth(string $expected, string $user, string $password = '')
|
||||
{
|
||||
$this->assertSame($expected, (new HttpOptions())->setAuthBasic($user, $password)->toArray()['auth_basic']);
|
||||
}
|
||||
}
|
@ -26,7 +26,9 @@ use Symfony\Contracts\HttpClient\Test\HttpClientTestCase;
|
||||
interface HttpClientInterface
|
||||
{
|
||||
public const OPTIONS_DEFAULTS = [
|
||||
'auth_basic' => null, // string - a username:password enabling HTTP Basic authentication (RFC 7617)
|
||||
'auth_basic' => null, // array|string - an array containing the username as first value, and optionally the
|
||||
// password as the second one; or string like username:password - enabling HTTP Basic
|
||||
// authentication (RFC 7617)
|
||||
'auth_bearer' => null, // string - a token enabling HTTP Bearer authorization (RFC 6750)
|
||||
'query' => [], // string[] - associative array of query string values to merge with the request's URL
|
||||
'headers' => [], // iterable|string[]|string[][] - headers names provided as keys or as part of values
|
||||
@ -37,16 +39,16 @@ interface HttpClientInterface
|
||||
// the JSON-encoded value and set the "content-type" headers to a JSON-compatible
|
||||
// value it is they are not defined - typically "application/json"
|
||||
'user_data' => null, // mixed - any extra data to attach to the request (scalar, callable, object...) that
|
||||
// MUST be available via $response->getInfo('data') - not used internally
|
||||
// MUST be available via $response->getInfo('data') - not used internally
|
||||
'max_redirects' => 20, // int - the maximum number of redirects to follow; a value lower or equal to 0 means
|
||||
// redirects should not be followed; "Authorization" and "Cookie" headers MUST
|
||||
// NOT follow except for the initial host name
|
||||
// redirects should not be followed; "Authorization" and "Cookie" headers MUST
|
||||
// NOT follow except for the initial host name
|
||||
'http_version' => null, // string - defaults to the best supported version, typically 1.1 or 2.0
|
||||
'base_uri' => null, // string - the URI to resolve relative URLs, following rules in RFC 3986, section 2
|
||||
'buffer' => true, // bool - whether the content of the response should be buffered or not
|
||||
'on_progress' => null, // callable(int $dlNow, int $dlSize, array $info) - throwing any exceptions MUST abort
|
||||
// the request; it MUST be called on DNS resolution, on arrival of headers and on
|
||||
// completion; it SHOULD be called on upload/download of data and at least 1/s
|
||||
// the request; it MUST be called on DNS resolution, on arrival of headers and on
|
||||
// completion; it SHOULD be called on upload/download of data and at least 1/s
|
||||
'resolve' => [], // string[] - a map of host to IP address that SHOULD replace DNS resolution
|
||||
'proxy' => null, // string - by default, the proxy-related env vars handled by curl SHOULD be honored
|
||||
'no_proxy' => null, // string - a comma separated list of hosts that do not require a proxy to be reached
|
||||
|
Reference in New Issue
Block a user