Search code examples
amazon-web-servicesamazon-s3yii2aws-sdkamazon-cloudfront

Issue with gzipping, sync of AWS S3, cloudfront and my server


What I am trying to achieve is to sync my static resources CSS, JS, images, uploded images(approx 1 million) to S3 bucket and deliver them using cloudfront. For syncing I am using AWS PHP SDK v2.8x. Following is my code:

    $folder = $_GET['folder'];
    $concurrency = $_GET['concurrency'];
    $force = $_GET['force'];
    $rootPath = Yii::$app->params['root_path'];
    $bucket = 'my-bucket';
    $client = S3Client::factory(array( 
        'key' => "my-key", 
        'secret' => "my-secret",
        'stats' => true
    ));
    $params = array();
    $metadata = array();
    $options = array();
    $params['ACL'] = 'public-read';
    //$params['ContentEncoding'] = 'gzip';
    $params['Expires'] = 'Wed, 20 Jun 2018 07:48:05 GMT';
    $params['CacheControl'] = 'max-age=31536000';
    $options['params'] = $params;
    $options['concurrency'] = $concurrency;
    //$options['debug'] = true;
    $options['force'] = $force;
    $client->uploadDirectory($rootPath.'/'.$folder, $bucket, $folder, $options);

I have successfully uploaded all content to S3 bucket and syncing with cloudfront is also working successfully. But the issue is I am unable to gzip any of this content resulting in huge page size. Also, expire headers are also not reflecting in cloudfront. If I enable $params['ContentEncoding'] = 'gzip'; I get ERR_CONTENT_DECODING_FAILED. I have made changes in CloudFront settings as well, but nothing seems to work. Also, please help me with best practices for syncing of S3, CloudFront and my server.

My current php framework is YII2.

Please tell me if addition information is needed, I will make edits.

Thanks in advance.


Solution

  • $params['ContentEncoding'] = 'gzip'; doesn't actually gzip your content -- it is used to indicate that you already gzipped it yourself before uploading it.

    If you set that, and you didn't gzip the content, then ERR_CONTENT_DECODING_FAILED would be correct.

    You can store the content in S3 uncompressed and just let CloudFront gzip it if you set Compress Objects Automatically to Yes in the CloudFront cache behavior.

    After setting up correctly, do a CloudFront cache invalidation for *, then test again.

    Also, don't set the Expires header. You almost certainly don't want that.

    When examining the headers from CloudFront, watch for Age. This is how long ago, in seconds, CloudFront fetched the object from S3.