Skip to content

Commit

Permalink
Merge pull request #54 from everly-gif/fix-trim-storage-endpoint
Browse files Browse the repository at this point in the history
Fix : Linode File Upload
  • Loading branch information
christyjacob4 authored Dec 9, 2022
2 parents f34c010 + 8e8a496 commit f19a200
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 42 deletions.
2 changes: 1 addition & 1 deletion src/Storage/Device/Local.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class Local extends Device
*/
public function __construct($root = '')
{
$this->root = $root;
$this->root = trim($root,"/");
}

/**
Expand Down
70 changes: 36 additions & 34 deletions src/Storage/Device/S3.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,22 +69,22 @@ class S3 extends Device
* @var string
*/
protected $bucket;

/**
* @var string
*/
protected $region;

/**
* @var string
*/
protected $acl = self::ACL_PRIVATE;

/**
* @var string
*/
protected $root = 'temp';

/**
* @var array
*/
Expand Down Expand Up @@ -113,9 +113,9 @@ public function __construct(string $root, string $accessKey, string $secretKey,
$this->secretKey = $secretKey;
$this->bucket = $bucket;
$this->region = $region;
$this->root = $root;
$this->root = trim($root, "/");
$this->acl = $acl;
$this->headers['host'] = $this->bucket . '.s3.'.$this->region.'.amazonaws.com';
$this->headers['host'] = $this->bucket . '.s3.' . $this->region . '.amazonaws.com';
$this->amzHeaders = [];
}

Expand Down Expand Up @@ -180,11 +180,11 @@ public function getPath(string $filename, string $prefix = null): string
*/
public function upload(string $source, string $path, int $chunk = 1, int $chunks = 1, array &$metadata = []): int
{
if($chunk == 1 && $chunks == 1) {
if ($chunk == 1 && $chunks == 1) {
return $this->write($path, \file_get_contents($source), \mime_content_type($source));
}
$uploadId = $metadata['uploadId'] ?? null;
if(empty($uploadId)) {
if (empty($uploadId)) {
$uploadId = $this->createMultipartUpload($path, $metadata['content_type']);
$metadata['uploadId'] = $uploadId;
}
Expand All @@ -194,7 +194,7 @@ public function upload(string $source, string $path, int $chunk = 1, int $chunks
$metadata['parts'][] = ['partNumber' => $chunk, 'etag' => $etag];
$metadata['chunks'] ??= 0;
$metadata['chunks']++;
if($metadata['chunks'] == $chunks) {
if ($metadata['chunks'] == $chunks) {
$this->completeMultipartUpload($path, $uploadId, $metadata['parts']);
}
return $metadata['chunks'];
Expand Down Expand Up @@ -236,18 +236,18 @@ protected function createMultipartUpload(string $path, string $contentType): str
*
* @return string
*/
protected function uploadPart(string $source, string $path, int $chunk, string $uploadId) : string
protected function uploadPart(string $source, string $path, int $chunk, string $uploadId): string
{
$uri = $path !== '' ? '/' . \str_replace(['%2F', '%3F'], ['/', '?'], \rawurlencode($path)) : '/';

$data = \file_get_contents($source);
$this->headers['content-type'] = \mime_content_type($source);
$this->headers['content-md5'] = \base64_encode(md5($data, true));
$this->amzHeaders['x-amz-content-sha256'] = \hash('sha256', $data);
unset($this->amzHeaders['x-amz-acl']); // ACL header is not allowed in parts, only createMultipartUpload accepts this header.

$response = $this->call(self::METHOD_PUT, $uri, $data, [
'partNumber'=>$chunk,
'partNumber' => $chunk,
'uploadId' => $uploadId
]);

Expand Down Expand Up @@ -277,7 +277,7 @@ protected function completeMultipartUpload(string $path, string $uploadId, array

$this->amzHeaders['x-amz-content-sha256'] = \hash('sha256', $body);
$this->headers['content-md5'] = \base64_encode(md5($body, true));
$this->call(self::METHOD_POST, $uri, $body , ['uploadId' => $uploadId]);
$this->call(self::METHOD_POST, $uri, $body, ['uploadId' => $uploadId]);
return true;
}

Expand Down Expand Up @@ -318,7 +318,7 @@ public function read(string $path, int $offset = 0, int $length = null): string
unset($this->headers['content-type']);
$this->headers['content-md5'] = \base64_encode(md5('', true));
$uri = ($path !== '') ? '/' . \str_replace('%2F', '/', \rawurlencode($path)) : '/';
if($length !== null) {
if ($length !== null) {
$end = $offset + $length - 1;
$this->headers['range'] = "bytes=$offset-$end";
}
Expand All @@ -339,7 +339,7 @@ public function read(string $path, int $offset = 0, int $length = null): string
public function write(string $path, string $data, string $contentType = ''): bool
{
$uri = $path !== '' ? '/' . \str_replace(['%2F', '%3F'], ['/', '?'], \rawurlencode($path)) : '/';

$this->headers['content-type'] = $contentType;
$this->headers['content-md5'] = \base64_encode(md5($data, true)); //TODO whould this work well with big file? can we skip it?
$this->amzHeaders['x-amz-content-sha256'] = \hash('sha256', $data);
Expand Down Expand Up @@ -387,7 +387,7 @@ public function move(string $source, string $target): bool
public function delete(string $path, bool $recursive = false): bool
{
$uri = ($path !== '') ? '/' . \str_replace('%2F', '/', \rawurlencode($path)) : '/';

unset($this->headers['content-type']);
unset($this->amzHeaders['x-amz-acl']);
unset($this->amzHeaders['x-amz-content-sha256']);
Expand Down Expand Up @@ -417,7 +417,7 @@ private function listObjects($prefix = '', $maxKeys = 1000, $continuationToken =
'prefix' => $prefix,
'max-keys' => $maxKeys,
];
if(!empty($continuationToken)) {
if (!empty($continuationToken)) {
$parameters['continuation-token'] = $continuationToken;
}
$response = $this->call(self::METHOD_GET, $uri, '', $parameters);
Expand All @@ -441,24 +441,24 @@ public function deletePath(string $path): bool
do {
$objects = $this->listObjects($path, continuationToken: $continuationToken);
$count = (int) ($objects['KeyCount'] ?? 1);
if($count < 1) {
if ($count < 1) {
break;
}
$continuationToken = $objects['NextContinuationToken'] ?? '';
$body = '<Delete xmlns="http://s3.amazonaws.com/doc/2006-03-01/">';
if($count > 1) {
if ($count > 1) {
foreach ($objects['Contents'] as $object) {
$body .= "<Object><Key>{$object['Key']}</Key></Object>";
}
} else {
$body .= "<Object><Key>{$objects['Contents']['Key']}</Key></Object>";
$body .= "<Object><Key>{$objects['Contents']['Key']}</Key></Object>";
}
$body .= '<Quiet>true</Quiet>';
$body .= '</Delete>';
$this->amzHeaders['x-amz-content-sha256'] = \hash('sha256', $body);
$this->headers['content-md5'] = \base64_encode(md5($body, true));
$this->call(self::METHOD_POST, $uri, $body, ['delete'=>'']);
} while(!empty($continuationToken));
$this->call(self::METHOD_POST, $uri, $body, ['delete' => '']);
} while (!empty($continuationToken));

return true;
}
Expand Down Expand Up @@ -523,7 +523,7 @@ public function getFileMimeType(string $path): string
public function getFileHash(string $path): string
{
$etag = $this->getInfo($path)['etag'] ?? '';
return (!empty($etag)) ? substr($etag, 1, -1) : $etag;
return (!empty($etag)) ? substr($etag, 1, -1) : $etag;
}

/**
Expand Down Expand Up @@ -624,10 +624,10 @@ private function getSignatureV4(string $method, string $uri, array $parameters =
$combinedHeaders[\strtolower($k)] = \trim($v);
}

uksort($combinedHeaders, [ & $this, 'sortMetaHeadersCmp']);
uksort($combinedHeaders, [&$this, 'sortMetaHeadersCmp']);

// Convert null query string parameters to strings and sort
uksort($parameters, [ & $this, 'sortMetaHeadersCmp']);
uksort($parameters, [&$this, 'sortMetaHeadersCmp']);
$queryString = \http_build_query($parameters, '', '&', PHP_QUERY_RFC3986);

// Payload
Expand All @@ -637,23 +637,25 @@ private function getSignatureV4(string $method, string $uri, array $parameters =
$amzPayload[] = ($qsPos === false ? $uri : \substr($uri, 0, $qsPos));

$amzPayload[] = $queryString;

foreach ($combinedHeaders as $k => $v) { // add header as string to requests
$amzPayload[] = $k . ':' . $v;
}

$amzPayload[] = ''; // add a blank entry so we end up with an extra line break
$amzPayload[] = \implode(';', \array_keys($combinedHeaders)); // SignedHeaders
$amzPayload[] = $this->amzHeaders['x-amz-content-sha256']; // payload hash

$amzPayloadStr = \implode("\n", $amzPayload); // request as string

// CredentialScope
$credentialScope = [$amzDateStamp, $region, $service, 'aws4_request'];

// stringToSign
$stringToSignStr = \implode("\n", [$algorithm, $this->amzHeaders['x-amz-date'],
\implode('/', $credentialScope), \hash('sha256', $amzPayloadStr)]);
$stringToSignStr = \implode("\n", [
$algorithm, $this->amzHeaders['x-amz-date'],
\implode('/', $credentialScope), \hash('sha256', $amzPayloadStr)
]);

// Make Signature
$kSecret = 'AWS4' . $this->secretKey;
Expand Down Expand Up @@ -683,7 +685,7 @@ private function getSignatureV4(string $method, string $uri, array $parameters =
*
* @return object
*/
private function call(string $method, string $uri, string $data = '', array $parameters=[])
private function call(string $method, string $uri, string $data = '', array $parameters = [])
{
$url = 'https://' . $this->headers['host'] . $uri . '?' . \http_build_query($parameters, '', '&', PHP_QUERY_RFC3986);
$response = new \stdClass;
Expand Down Expand Up @@ -739,7 +741,7 @@ private function call(string $method, string $uri, string $data = '', array $par
});
\curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
\curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);

// Request types
switch ($method) {
case self::METHOD_PUT:
Expand All @@ -753,11 +755,11 @@ private function call(string $method, string $uri, string $data = '', array $par
}

$result = \curl_exec($curl);

if (!$result) {
throw new Exception(\curl_error($curl));
}

$response->code = \curl_getinfo($curl, CURLINFO_HTTP_CODE);
if ($response->code >= 400) {
throw new Exception($response->body, $response->code);
Expand Down
2 changes: 1 addition & 1 deletion tests/Storage/Device/BackblazeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class BackblazeTest extends S3Base
{
protected function init(): void
{
$this->root = 'root';
$this->root = '/root';
$key = $_SERVER['BACKBLAZE_ACCESS_KEY'] ?? '';
$secret = $_SERVER['BACKBLAZE_SECRET'] ?? '';
$bucket = "backblaze-demo";
Expand Down
2 changes: 1 addition & 1 deletion tests/Storage/Device/LinodeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class LinodeTest extends S3Base
{
protected function init(): void
{
$this->root = 'root';
$this->root = '/root';
$key = $_SERVER['LINODE_ACCESS_KEY'] ?? '';
$secret = $_SERVER['LINODE_SECRET'] ?? '';
$bucket = 'everly-test';
Expand Down
4 changes: 2 additions & 2 deletions tests/Storage/Device/LocalTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ public function testDescription()

public function testRoot()
{
$this->assertEquals($this->object->getRoot(),realpath( __DIR__ . '/../../resources/disk-a'));
$this->assertEquals($this->object->getRoot(),trim(realpath( __DIR__ . '/../../resources/disk-a'),"/"));
}

public function testPath()
{
$this->assertEquals($this->object->getPath('image.png'), realpath(__DIR__ . '/../../resources/disk-a').'/image.png');
$this->assertEquals($this->object->getPath('image.png'), trim(realpath(__DIR__ . '/../../resources/disk-a').'/image.png',"/"));
}

public function testWrite()
Expand Down
2 changes: 1 addition & 1 deletion tests/Storage/Device/WasabiTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class WasabiTest extends S3Base
{
protected function init(): void
{
$this->root = 'root';
$this->root = '/root';
$key = $_SERVER['WASABI_ACCESS_KEY'] ?? '';
$secret = $_SERVER['WASABI_SECRET'] ?? '';
$bucket = 'utopia-storage-tests';
Expand Down
4 changes: 2 additions & 2 deletions tests/Storage/S3Base.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,12 @@ public function testDescription()

public function testRoot()
{
$this->assertEquals($this->root, $this->object->getRoot());
$this->assertEquals( trim($this->root, "/"), $this->object->getRoot());
}

public function testPath()
{
$this->assertEquals($this->root . '/image.png', $this->object->getPath('image.png'));
$this->assertEquals(trim($this->root, "/") . '/image.png', $this->object->getPath('image.png'));
}

public function testWrite()
Expand Down

0 comments on commit f19a200

Please sign in to comment.