diff --git a/src/Client.php b/src/Client.php index 3064342..038ab56 100644 --- a/src/Client.php +++ b/src/Client.php @@ -1614,7 +1614,7 @@ private function json($data) * * Description from Docker's docs (see links): * - * AuthConfig, set as the X-Registry-Auth header, is currently a Base64 + * AuthConfig, set as the X-Registry-Auth header, is currently a base64url * encoded (JSON) string with the following structure: * ``` * {"username": "string", "password": "string", "email": "string", "serveraddress" : "string", "auth": ""} @@ -1632,7 +1632,7 @@ private function authHeaders($registryAuth) { $headers = array(); if ($registryAuth !== null) { - $headers['X-Registry-Auth'] = base64_encode($this->json($registryAuth)); + $headers['X-Registry-Auth'] = strtr(base64_encode($this->json($registryAuth)), '+/', '-_'); } return $headers; diff --git a/tests/ClientTest.php b/tests/ClientTest.php index 8f3ff1b..a2c0ee5 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -573,7 +573,6 @@ public function testImagePushStream() public function testImagePushCustomRegistry() { - // TODO: verify headers $auth = array(); $json = array(); $stream = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock(); @@ -585,6 +584,19 @@ public function testImagePushCustomRegistry() $this->expectPromiseResolveWith($json, $this->client->imagePush('123', 'test', 'demo.acme.com:5000', $auth)); } + public function testImagePushWithRegistryAuth() + { + $auth = array('username' => 'user', 'password' => 'p>ss?word!'); + $json = array(); + $stream = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock(); + + $this->browser->expects($this->once())->method('requestStreaming')->with('POST', 'images/123/push', array('X-Registry-Auth' => 'eyJ1c2VybmFtZSI6InVzZXIiLCJwYXNzd29yZCI6InA-c3M_d29yZCEifQ=='))->willReturn(\React\Promise\resolve($this->createResponseJsonStream($json))); + $this->streamingParser->expects($this->once())->method('parseJsonStream')->willReturn($stream); + $this->streamingParser->expects($this->once())->method('deferredStream')->with($stream)->willReturn(\React\Promise\resolve($json)); + + $this->expectPromiseResolveWith($json, $this->client->imagePush('123', null, null, $auth)); + } + public function testImageTag() { $this->expectRequestFlow('post', 'images/123/tag?repo=test', $this->createResponse(), 'expectEmpty');