おかしいぞ!? S3から404が返ってくる。
ニシザワです。
本日は、Laravelで画像をS3へアップロードまたは削除する際の存在チェックで404になりハマったのでそちらについて書きます。
エラー内容
[object] (GuzzleHttp\\Exception\\ClientException(code: 404): Client error: `GET https://xxxxxx.s3-ap-northeast-1.amazonaws.com/images/hogehoge.jpg` resulted in a `404 Not Found` response:
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<Error><Code>NoSuchKey</Code><Message>The specified key does not exist.</Message> (truncated...)
S3でファイルが存在しない場合は403が基本的に返されるはずです。
Laravelのファイルシステムのclassを見てみると
private function checkExistenceWithCommand(CommandInterface $command)
{
try {
$this->execute($command);
return true;
} catch (S3Exception $e) {
if ($e->getAwsErrorCode() == 'AccessDenied') {
return true;
}
if ($e->getStatusCode() >= 500) {
throw $e;
}
return false;
}
}
AccessDeniedで判定しています。
今回は存在しない場合404。
おかしいぞ。
公式には404で返すと書いてあるでは有りませんか!!
ということは、Laravelのファイルシステムが悪い?
結論からお伝えすると、なぜ404で帰ってくるのかわからず。。。
Cloud Frontの設定で404を返すようにしていますが、今回Cloud Frontから存在チェックしているわけではないので違う気がします。
取り敢えず解決策
try {
Storage::disk('s3')->delete('hoge/fuga.jpg');
} catch (S3Exception $e) {
if ($e->getStatusCode() !== 404) {
throw $e;
}
}
try {
Storage::disk('s3')->exists('hoge/fuga.jpg');
} catch (S3Exception $e) {
if ($e->getStatusCode() !== 404) {
throw $e;
}
}
S3Exceptionを返してくれるので、try catchで捕まえてみました。
こうすることで、404の場合でも次の処理に移すことができる形になります。
ご参考までに。