ZF2-268: AmazonS3 service broken

Issue Type: Bug Created: 2012-04-17T08:53:49.000+0000 Last Updated: 2012-07-19T12:12:22.000+0000 Status: Resolved Fix version(s): Reporter: Andrey (special) Assignee: Duccio Gasparri (dgasparri) Tags: - Zend\Cloud

  • amazon

Related issues: Attachments: - http-client-set-auth.patch


<pre class="highlight">
$s = new \Zend\Service\Amazon\S3\S3($amazonKey,$amazonSecret);

result: bq. Warning: Missing argument 2 for Zend\Http\Client::setAuth(), called in /vendor/ZendFramework/library/Zend/Service/Amazon/S3/S3.php on line 624 and defined in /vendor/ZendFramework/library/Zend/Http/Client.php on line 635

And exception: bq. The username and the password cannot be empty


<pre class="highlight">
624 $client->setAuth(false);

635 public function setAuth($user, $password, $type = self::AUTH_BASIC)

Please check this service.


Posted by simon liu (simonliu) on 2012-04-18T05:12:39.000+0000

$client->setAuth(false); means disable http auth, but Zend\Http\Client does not support it yet, I create a patch to support it.

Posted by simon liu (simonliu) on 2012-04-18T05:13:49.000+0000

support setAuth(false)

Posted by Andrey (special) on 2012-04-18T06:32:37.000+0000

Thank you, Simon Liu! But apparently, this class Zend\Service\Amazon\S3 has not yet upgraded to ZF2.

Because the line 651

<pre class="highlight">
651 $response = $client->request($method);

But new class Zend\Http\Client don't have method request(), although the old class Zend_Http_Client have request() method.

Can you finish this S3 class? Or when it is planned to be done?

Thank you!

Posted by Enrico Zimuel (zimuel) on 2012-04-18T06:47:56.000+0000

We have to refactor the Zend\Service\Amazon component with the new Zend\Http\Client. We will do that in the next beta (not beta4).

Posted by Andrey (special) on 2012-04-18T06:56:05.000+0000

Enrico, thanks for the info!

Posted by David Windell (outeredge) on 2012-05-01T10:38:33.000+0000

Can we have confirmation this will be fixed in beta4, this prevents usage of the S3 component and shouldn't be included if not working at all.

Posted by Duccio Gasparri (dgasparri) on 2012-05-09T10:21:34.000+0000

This line appears to be useless because two rows above in S3::_makeRequest() there is $client->resetParameters():

622 $client->resetParameters(); 623 $client->setUri($endpoint); 624 $client->setAuth(false);

resetParameters already resets the Auth.

Posted by Duccio Gasparri (dgasparri) on 2012-05-09T10:40:59.000+0000

Closely related to this bug, on the next line there's

    // Work around buglet in HTTP client - it doesn't clean headers
    // Remove when ZHC is fixed
    $client->setHeaders(array('Content-MD5'              => null,
                              'Expect'                   => null,
                              'Range'                    => null,
                              'x-amz-acl'                => null,
                              'x-amz-copy-source'        => null,
                              'x-amz-metadata-directive' => null));


The first setHeaders raises an exception. setHeader now replaces the old headers, so it is safe to take away the first setHeader and just leave the $client->setHeaders($headers);

Posted by Maks 3w (maks3w) on 2012-05-09T10:47:40.000+0000

If you think that you can fix this submit a patch to Github (

Also could be very interesting provide a unit test for this.

Posted by Duccio Gasparri (dgasparri) on 2012-05-09T10:49:06.000+0000

Sorry, but one small bug after another, I believe I fixed it.

Posted by Duccio Gasparri (dgasparri) on 2012-05-09T10:58:56.000+0000

I've never written a unit test for a http-based service. To your knowledge, is there other examples that could be used as a starting point?

Posted by Maks 3w (maks3w) on 2012-05-09T11:07:08.000+0000

Any of this… can help you.

For example, if you want add the test to…

then create a function like this 'public function testXXXXX()' and put in the body something like this:

$s3 = new S3(); ...

$actual = s3->getXXX(); $expects = 'Foo';

$this->assertEqual($expects, $actual);

As you can see the first part is test the function, then you storage the result in a var and finally you test if the result is the same of you expects.

This can help you…

Posted by Duccio Gasparri (dgasparri) on 2012-05-10T16:31:44.000+0000

I tested it for a couple of days and put the relevant changes to pull #1194

Thank you Maks for the info on unit test. I know more or less how to write a unit test, but I don't know what's the standard for writing a unit test based on an external service: unless you create a fake in-out stream (is it possible? isn't it crazy?), or anyway a test-repo on S3 or a public sandbox by the service owner, results will be always variable depending on the status of the external service.

However, it appears that there's already a neatly written test for the S3 service… . At a first glance it should work, but I haven't run it yet.

Posted by Maks 3w (maks3w) on 2012-05-10T17:57:20.000+0000

To avoid unexpected responses from a external service you should create a Mockup (…) Is a little more complex to learn how to use but I tell you the idea behind this.

I will guess the following scenario (I don't know the internals of S3) You request an authorization and S3 transform your request in a Http response

User/Pass <=> S3::auth($parameters) <=> Zend\Http\Client::send($request)

The goal here is that when Http\Client receive $request you already know if S3::auth() do his works correctly.

Then we want convert Http\Client in a mockup object and then you setup something as following (pseudocode):

$mock = createMockup(Zend\Http\Client) $mock -> method(send) $mock -> expects($request = http://amazon/?u=User&p=Pass) $mock -> return(the expected Http result to use inside of S3)

Now we need inject our mockup inside of S3 class. We need something like S3::setHttpClient($mock)

Then when you execute the test you can be sure about the functionality.

Of course we are talking about Unit Tests where the scope is limited to test the code of the function. Other tests are Functional Tests where we don't use mockups and we do direct connections to AWS servers (OnlineTests.php)

You can enter to the IRC if you need more help. #zftalk.2 in

Posted by Maks 3w (maks3w) on 2012-05-11T13:10:03.000+0000

Fixed with

Posted by Maks 3w (maks3w) on 2012-05-11T14:47:30.000+0000

I wrote a small test to verify the responses for getBuckets() this test not verify the auth issue described above but could give you an example about how works the mockups.

Posted by Boris (boristm) on 2012-07-17T11:18:00.000+0000

After upgrading from beta4 to beta5 the S3 service stopped working: all the operations (for example, getBuckets) leads to an error in the response of the service: ‘The request signature we calculated does not match the signature you provided. Check your key and signing method.’

In beta4 it works.

I’ve checked the difference between beta4 and beta5 and found the calculating of signature was changed in addSignature method of S3 class.

In beta4 it was:

<pre class="highlight">
$signature = base64_encode(Hmac::compute($this->_getSecretKey(), 'sha1', utf8_encode($sig_str), Hmac::OUTPUT_BINARY));

In beta5 it is:

<pre class="highlight">
$signature = base64_encode(Hmac::compute($this->_getSecretKey(), 'sha1', utf8_encode($sig_str), true));

Could you please explain why the last argument of Hmac::compute was changed in this way? Or if it was made by mistake could you roll back this?

Posted by Maks 3w (maks3w) on 2012-07-19T11:50:31.000+0000

Hi [~boristm] could you open your issue in a new one?

Posted by Boris (boristm) on 2012-07-19T12:12:22.000+0000

here is:

Have you found an issue?

See the Overview section for more details.


© 2006-2018 by Zend, a Rogue Wave Company. Made with by awesome contributors.

This website is built using zend-expressive and it runs on PHP 7.