Describe the bug
When invoking 'doesObjectExist()` with the S3 client, the API returns TRUE for non-existing objects.
Expected Behavior
The API should return TRUE if the specified bucket and key exists.
The API should return FALSE if the specified bucket does not exist, or if the specified bucket and key do not exist.
Current Behavior
The API always returns true.
Reproduction Steps
$params = [
'Bucket' => 'my-bucket-which-exists',
// Non-existent key name.
'Key' => 'sdsgfdsgregerdfdgdd',
];
$result = $s3Client->doesObjectExist($params['Bucket'], $params['Key']);
Possible Solution
The method checkExistenceWithCommand() in the S3ClientTrait executes a defined command.
If the command does not throw an exception, TRUE is returned.
/**
* Determines whether or not a resource exists using a command
*
* @param CommandInterface $command Command used to poll for the resource
*
* @return bool
* @throws S3Exception|\Exception if there is an unhandled exception
*/
private function checkExistenceWithCommand(CommandInterface $command)
{
try {
$result = $this->execute($command);
return true;
} catch (S3Exception $e) {
if ($e->getAwsErrorCode() == 'AccessDenied') {
return true;
}
if ($e->getStatusCode() >= 500) {
throw $e;
}
return false;
}
}
The doesObjectExist() method uses a HeadObject command to check if the bucket exists.
/**
* @see S3ClientInterface::doesObjectExist()
*/
public function doesObjectExist($bucket, $key, array $options = [])
{
return $this->checkExistenceWithCommand(
$this->getCommand('HeadObject', [
'Bucket' => $bucket,
'Key' => $key
] + $options)
);
}
When executing a HeadObject command for a non-existing key, the command does not throw an Exception.
Instead, it returns the 404 response as an Aws\Result object.
class Aws\Result#2316 (2) {
private $data =>
array(1) {
'@metadata' =>
array(4) {
'statusCode' =>
int(404)
'effectiveUri' =>
string(55) "https://<redacted>.s3.amazonaws.com/sdsgfdsgregerdfdgdd"
'headers' =>
array(5) {
...
}
'transferStats' =>
array(1) {
...
}
}
}
private $monitoringEvents =>
array(0) {
}
}
Additional Information/Context
The most significant end-user impact is that using mkdir() with the S3 StreamWrapper always fails, because it always believes the (pseudo)-directory exists.
Solution options may include:
- Within
checkExistenceWithCommand(), test for a 404 result (in addition to detecting an exception).
- Within the
HeadObject command, throw an Exception for non-existing objects.
SDK version used
3.222.6
Environment details (Version of PHP (php -v)? OS name and version, etc.)
PHP 7.4.29 (cli), on Ubuntu Bionic 18.04.
Describe the bug
When invoking 'doesObjectExist()` with the S3 client, the API returns TRUE for non-existing objects.
Expected Behavior
The API should return TRUE if the specified bucket and key exists.
The API should return FALSE if the specified bucket does not exist, or if the specified bucket and key do not exist.
Current Behavior
The API always returns true.
Reproduction Steps
Possible Solution
The method
checkExistenceWithCommand()in theS3ClientTraitexecutes a defined command.If the command does not throw an exception, TRUE is returned.
The
doesObjectExist()method uses aHeadObjectcommand to check if the bucket exists.When executing a
HeadObjectcommand for a non-existing key, the command does not throw an Exception.Instead, it returns the
404response as anAws\Resultobject.Additional Information/Context
The most significant end-user impact is that using
mkdir()with the S3 StreamWrapper always fails, because it always believes the (pseudo)-directory exists.Solution options may include:
checkExistenceWithCommand(), test for a 404 result (in addition to detecting an exception).HeadObjectcommand, throw an Exception for non-existing objects.SDK version used
3.222.6
Environment details (Version of PHP (
php -v)? OS name and version, etc.)PHP 7.4.29 (cli), on Ubuntu Bionic 18.04.