Skip to content

Instantly share code, notes, and snippets.

@charlie-s
Created April 2, 2015 23:53
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save charlie-s/89cb8b4d430c8e08d938 to your computer and use it in GitHub Desktop.
Save charlie-s/89cb8b4d430c8e08d938 to your computer and use it in GitHub Desktop.
S3 PHP Example (without an SDK)
<?php
class S3 {
private $key = 'ABC123';
private $secret = 'lolftw';
private $region = 'us-west-2';
private $bucket = 'examplebucket';
private $host = 's3.amazonaws.com';
public function uploadFile($file_path) {
$default_timezone = date_default_timezone_get();
date_default_timezone_set('UTC');
$file_contents = file_get_contents($file_path);
$file_name = basename($file_path);
$hashed_payload = hash('sha256', $file_contents);
$date_full = date('D, d M Y H:i:s \G\M\T'); // @todo don't force GMT!
$date_time = date('Ymd\THisZ'); // @todo don't force Z!
$date = date('Ymd');
// Set headers.
$headers = array(
'Host' => $this->bucket . '.' . $this->host,
'Content-Type' => mime_content_type($file_name),
'x-amz-content-sha256' => $hashed_payload,
'x-amz-date' => $date_full,
);
ksort($headers);
$signed_headers_string = strtolower(implode(';', array_keys($headers)));
// Build canonical request.
$canonical_request = "PUT\n"; // HTTP Method
$canonical_request .= '/' . urlencode($file_name) . "\n"; // Canonical URI
$canonical_request .= "\n"; // CanonicalQueryString
foreach ($headers as $header => $value) {
$canonical_request .= strtolower($header) . ':' . trim($value) . "\n";
}
$canonical_request .= "\n";
$canonical_request .= $signed_headers_string . "\n"; // SignedHeaders
$canonical_request .= $hashed_payload; // HashedPayload
print "\n\nCanonical Request:\n" . $canonical_request;
// Build string to sign.
$string_to_sign = "AWS4-HMAC-SHA256\n";
$string_to_sign .= $date_full . "\n";
$string_to_sign .= $date . '/' . $this->region . "/s3/aws4_request\n";
$string_to_sign .= hash('sha256', $canonical_request);
print "\n\nString to Sign:\n" . $string_to_sign;
// Calculate signature.
$signature_date = hash_hmac('sha256', $date, 'AWS4' . $this->secret, true);
$signature_region = hash_hmac('sha256', $this->region, $signature_date, true);
$signature_service = hash_hmac('sha256', 's3', $signature_region, true);
$signature_request = hash_hmac('sha256', 'aws4_request', $signature_service, true);
$signature = hash_hmac('sha256', $string_to_sign, $signature_request);
// Calculate final `Authorization` header.
$headers['Authorization'] = 'AWS4-HMAC-SHA256 Credential=' . $this->key . '/' . $date . '/' . $this->region . '/s3/aws4_request,';
$headers['Authorization'] .= 'SignedHeaders=' . $signed_headers_string . ',';
$headers['Authorization'] .= 'Signature=' . $signature;
print "\n\nAuthorization:\n" . $headers['Authorization'];
// Convert headers to key:value strings.
$curl_headers = array();
foreach ($headers as $header => $value) {
$curl_headers[] = "{$header}:{$value}";
}
// Init curl.
$curl = curl_init();
$url = 'https://' . $this->bucket . '.' . $this->host . '/' bu. $file_name;
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_VERBOSE, 1);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($curl, CURLINFO_HEADER_OUT, true);
curl_setopt($curl, CURLOPT_HEADER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, $curl_headers);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $file_contents);
// Run request.
if ($result = curl_exec($curl)) {
print "\n\nSuccess!\n";
$curl_info = curl_getinfo($curl, CURLINFO_HTTP_CODE);
print_r($curl_info);
print_r($result);
print "\n\nHeaders sent:\n";
$headers_sent = curl_getinfo($curl, CURLINFO_HEADER_OUT);
print_r($headers_sent);
}
else {
print "\n\nError!\n";
print_r(array(
'code' => curl_errno($curl),
'message' => curl_error($curl),
));
}
@curl_close($curl);
date_default_timezone_set($default_timezone);
}
}
$foo = new S3();
$foo->uploadFile(__DIR__ . '/test.txt');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment