Question:
I have create a signed $URL for Amazon s3 and it opens perfectly in the browser.
1 2 |
http://testbucket.com.s3.amazonaws.com/100-game-play-intro-1.m4v?AWSAccessKeyId=AKIAJUAjhkhkjhMO73BF5Q&Expires=1378465934&Signature=ttmsAUDgJjCXepwEXvl8JdFu%2F60%3D |
**Bucket name and accesskey changed in this example
I am however trying to then use the function below to check (using curl) that the file exists. It fails the CURL connection. If I replace $URL above with the url of an image outside of s3 then this code works perfectly.
I know the file exists in amazon but can’t work out why this code fails if using a signed url as above
Any ideas?
Thanks
Here is my code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
function remoteFileExists($url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_RETURNTRANSFER, false); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //don't fetch the actual file, only get header to check if file exists curl_setopt($ch, CURLOPT_HEADER, 1); curl_setopt($ch, CURLOPT_NOBODY, true); $result = curl_exec($ch); curl_close($ch); if ($result !== false) { $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); if ($statusCode == 200) { $ret = true; } else { $ret = false; } } else { $ret='connection failed'; } return $ret; } |
Answer:
When using CURLOPT_NOBODY, libcurl sends an HTTP HEAD
request, not a GET
request.
…the string to be signed is formed by appending the REST verb, content-md5 value, content-type value, expires parameter value, canonicalized x-amz headers (see recipe below), and the resource; all separated by newlines.
— http://s3.amazonaws.com/doc/s3-developer-guide/RESTAuthentication.html
The “REST verb” — e.g., GET
vs HEAD
— must be consistent between the signature you generate, and the request that make, so a signature that is valid for GET
will not be valid for HEAD
and vice versa.
You will need to sign a HEAD
request instead of a GET
request in order to validate a file in this way.