Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/Storage/Device/Local.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Exception;
use Utopia\Storage\Device;
use Utopia\Storage\Exception\NotFoundException;
use Utopia\Storage\Storage;

class Local extends Device
Expand Down Expand Up @@ -272,7 +273,7 @@ public function abort(string $path, string $extra = ''): bool
public function read(string $path, int $offset = 0, int $length = null): string
{
if (! $this->exists($path)) {
throw new Exception('File Not Found');
throw new NotFoundException('File not found');
}

return \file_get_contents($path, use_include_path: false, context: null, offset: $offset, length: $length);
Expand Down
35 changes: 33 additions & 2 deletions src/Storage/Device/S3.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Exception;
use Utopia\Storage\Device;
use Utopia\Storage\Exception\NotFoundException;
use Utopia\Storage\Storage;

class S3 extends Device
Expand Down Expand Up @@ -284,7 +285,7 @@ public function transfer(string $path, string $destination, Device $device): boo
try {
$response = $this->getInfo($path);
} catch (\Throwable $e) {
throw new Exception('File not found');
throw new NotFoundException('File not found');
}
$size = (int) ($response['content-length'] ?? 0);
$contentType = $response['content-type'] ?? '';
Expand Down Expand Up @@ -903,7 +904,7 @@ protected function call(string $operation, string $method, string $uri, string $
}

if ($response->code >= 400) {
throw new Exception($response->body, $response->code);
$this->parseAndThrowS3Error($response->body, $response->code);
}

// Parse body into XML
Expand All @@ -927,6 +928,36 @@ protected function call(string $operation, string $method, string $uri, string $
}
}

/**
* Parse S3 XML error response and throw appropriate exception
*
* @param string $errorBody The error response body
* @param int $statusCode The HTTP status code
*
* @throws NotFoundException When the error is NoSuchKey
* @throws Exception For other S3 errors
*/
private function parseAndThrowS3Error(string $errorBody, int $statusCode): void
{
if (str_starts_with($errorBody, '<?xml')) {
try {
$xml = \simplexml_load_string($errorBody);
$errorCode = (string) ($xml->Code ?? '');
$errorMessage = (string) ($xml->Message ?? '');

if ($errorCode === 'NoSuchKey') {
throw new NotFoundException($errorMessage ?: 'File not found', $statusCode);
}
} catch (NotFoundException $e) {
throw $e;
} catch (\Throwable $e) {
// If XML parsing fails, fall through to original error
}
}

throw new Exception($errorBody, $statusCode);
}

/**
* Sort compare for meta headers
*
Expand Down
9 changes: 9 additions & 0 deletions src/Storage/Exception/NotFoundException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace Utopia\Storage\Exception;

use Exception;

class NotFoundException extends Exception
{
}
7 changes: 7 additions & 0 deletions tests/Storage/Device/LocalTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use PHPUnit\Framework\TestCase;
use Utopia\Storage\Device\AWS;
use Utopia\Storage\Device\Local;
use Utopia\Storage\Exception\NotFoundException;

class LocalTest extends TestCase
{
Expand Down Expand Up @@ -75,6 +76,12 @@ public function testRead()
$this->object->delete($this->object->getPath('text-for-read.txt'));
}

public function testReadNonExistentFile()
{
$this->expectException(NotFoundException::class);
$this->object->read($this->object->getPath('non-existent-file.txt'));
}

public function testFileExists()
{
$this->assertEquals($this->object->write($this->object->getPath('text-for-test-exists.txt'), 'Hello World'), true);
Expand Down
23 changes: 18 additions & 5 deletions tests/Storage/S3Base.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use PHPUnit\Framework\TestCase;
use Utopia\Storage\Device\Local;
use Utopia\Storage\Device\S3;
use Utopia\Storage\Exception\NotFoundException;

abstract class S3Base extends TestCase
{
Expand All @@ -20,11 +21,6 @@ abstract protected function getAdapterName(): string;
*/
abstract protected function getAdapterDescription(): string;

/**
* @return string
*/
abstract protected function getAdapterType(): string;

/**
* @var S3
*/
Expand Down Expand Up @@ -138,6 +134,12 @@ public function testRead()
$this->object->delete($this->object->getPath('text-for-read.txt'));
}

public function testReadNonExistentFile()
{
$this->expectException(NotFoundException::class);
$this->object->read($this->object->getPath('non-existent-file.txt'));
}

public function testFileExists()
{
$this->assertEquals(true, $this->object->exists($this->object->getPath('testing/kitten-1.jpg')));
Expand Down Expand Up @@ -415,4 +417,15 @@ public function testTransferSmall()
$this->object->delete($path);
$device->delete($destination);
}

public function testTransferNonExistentFile()
{
$device = new Local(__DIR__.'/../resources/disk-a');

$path = $this->object->getPath('non-existent-file.txt');
$destination = $device->getPath('hello.txt');

$this->expectException(NotFoundException::class);
$this->object->transfer($path, $destination, $device);
}
}