Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set proper endpoint in for S3 Client in Amazon AWS PHP SDK

I'm trying to use the AWS SDK for PHP to programatically upload a file to a bucket that's set to be a static website in the S3 Console.

The bucket is named foo.ourdomain.com and is hosted in eu-west. I'm using the following code to try and test if I can upload a file:

  $client = \Aws\S3\S3Client::factory(array('key' => bla, 'secret' => bla));
  $client->upload('foo.ourdomain.com', 'test.txt', 'hello world', 'public-read');

This is pretty much like it is in the examples, however, I received the following exception:

PHP Fatal error: Uncaught Aws\S3\Exception\PermanentRedirectException: AWS Error Code: PermanentRedirect, Status Code: 301, AWS Request ID: -, AWS Error Type: client, AWS Error Message: The bucket you are attempting to access must be addressed using the specified endpoint. Please send all future requests to this endpoint: "foo.ourdomain.com.s3.amazonaws.com"., User-Agent: aws-sdk-php2/2.4.8 Guzzle/3.7.4 curl/7.22.0 PHP/5.3.10-1ubuntu3.8

At this point I was surprised as there's no mention of this in the manual for the S3 SDK. But okay, I found a method setEndpoint and adjusted the code to:

   $client = \Aws\S3\S3Client::factory(array('key' => bla, 'secret' => bla));
   $client->setEndpoint('foo.ourdomain.com.s3.amazonaws.com');
   $client->upload('foo.ourdomain.com', 'test.txt', 'hello world', 'public-read');

I assumed that'd work, but I'm getting the exact same error. I've doublechecked and the endpoint mentioned in the exception byte-for-byte matches the one I'm setting in the second line.

I've also tried using foo.ourdomain.com.s3-website-eu-west-1.amazonaws.com as the endpoint (this is the host our CNAME points to as per the S3 consoles instructions). Didn't work either.

I must be missing something, but I can't find it anywhere. Perhaps buckets set to 'static website' behave differently in a way which is not currently supported by the SDK? If so, I can't find mention of it in the docs nor in the management console.

like image 688
Marlies Avatar asked Nov 04 '13 12:11

Marlies


2 Answers

Got it. The solution was to change the initialisation of the client to:

$client = \Aws\S3\S3Client::factory(array(
  'key' => bla, 
  'secret' => bla, 
  'region' => 'eu-west-1'
));

I.e. rather than specify an endpoint I needed to explicitly set the region in the options array. I guess the example code happens to use whatever the default region is.

like image 121
Marlies Avatar answered Oct 04 '22 00:10

Marlies


If you don't want to initialize the client to a specific region and/or you'll need to work with different regions, I have been successful in using the getBucketLocation/setRegion set of calls as follows:

// Bucket location is fetched
$m_bucketLocation = $I_s3->getBucketLocation(array(
        'Bucket' => $s_backupBucket,
));
// Bucket location is specified before operation is made
$I_s3->setRegion($m_bucketLocation['Location']);

I have one extra call, but solved my issue without the need to intervene on the factory.

like image 45
maraspin Avatar answered Oct 04 '22 00:10

maraspin