How to add required ContentMD5 to Bucket Policy PUT request for lifecycle, cors or acl?

I am going to answer my own question here. It took me hours to figure this out as there is no info on this anywhere so I thought I should post this somewhere I would look first.

I was using the AWS PHP SDK to send a PUT request to add a lifecycle policy to my Digital Ocean space and it would not take since it requires a ContentMD5 header. There are two problems here, the first problem is the SDK URL encodes the path/key, which is a problem with /?lifecycle, /?location, and /?acl since they become “/%3Flifecycle” – skip this paragraph if this isn’t part of your request path. To temporarily stop this to add or update a bucket policy you have to find the file RestSerializer.php in the SDK files, if you added the API with composer it will be in a path like /vendor/aws/aws-sdk-php/src/Api/Serializer/RestSerializer.php in your composer/websites root, which will likely be in /var/www. In RestSerializer.php find the two rawurlencode function calls and remove them but leave the value/argument “rawurlencode($varspecs[$k])” becomes “$varspecs[$k]”.

Now the request is going to the correct URL, to generate the ContentMD5 you need to construct a little PHP code depending on what you’re doing. If you have put the XML text for your policy in a file use md5_file(PATH_TO_FILE_HERE, true) if you are using a string use md5(STRING_HERE, true). Then wrap that in base64_encode() so it looks something like base64_encode(md5_file(‘/path/file.xml’, true)). Finally, add that to your putObject array with ‘ContentMD5’ => base64_encode(md5_file(‘/path/file.xml’, true)) .

PHP Example with File:

// $spaceS3Client is a new S3Client object.

// since its a file, I need to get the file first $xmlfile = fopen(‘/spaces.xml’, ‘r+’);

$request = $spaceS3Client->putObject([ ‘Bucket’ => ‘myspacename’, ‘Key’ => ‘?lifecycle’, ‘Body’ => $xmlfile, ‘ContentType’ => ‘application/xml’, ‘ContentMD5’ => base64_encode(md5_file(‘/spaces.xml’', true)) ]);

// close file fclose($xmlfile);

// if you are having trouble connecting to your space in the first place with an S3Client object, since its set up for AWS and not DO you need to add an ‘endpoint’ to the array in new S3Client like ‘endpoint’ => ‘https://’.$myspace.‘.’.$myspaceregion.‘’. You also need to add ‘bucket_endpoint’ => true.

Submit an answer

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Sign In or Sign Up to Answer

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

Want to learn more? Join the DigitalOcean Community!

Join our DigitalOcean community of over a million developers for free! Get help and share knowledge in Q&A, subscribe to topics of interest, and get courses and tools that will help you grow as a developer and scale your project or business.

I need to correct the above since it is no longer working, replace fopen with file_get_contents, remove fclose and to check the rules have been set use a get request then you can display the result with header(‘Content-type: text/xml’); $request = $request->toArray()[“Body”]; echo $request;

The answer is the question, oh that sounds like a puzzle, just read the above.