mirror of
https://code.castopod.org/adaures/castopod
synced 2025-04-22 16:51:20 +00:00
fix(s3): remove proxy, set objects acl to public-read, and serve files using their public urls
This commit is contained in:
parent
de099ac643
commit
6a77a9d2f2
@ -33,7 +33,6 @@ class Media extends BaseConfig
|
||||
'debug' => false,
|
||||
'pathStyleEndpoint' => false,
|
||||
'keyPrefix' => '',
|
||||
'serveWithRedirect' => false,
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -1,24 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use CodeIgniter\Router\RouteCollection;
|
||||
|
||||
/**
|
||||
* @copyright 2023 Ad Aures
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
||||
* @link https://castopod.org/
|
||||
*/
|
||||
|
||||
/** @var RouteCollection $routes */
|
||||
|
||||
$routes->head('static/(:any)', 'MediaController::serve/$1', [
|
||||
'as' => 'media-serve',
|
||||
'namespace' => 'Modules\Media\Controllers',
|
||||
'filter' => 'allow-cors',
|
||||
]);
|
||||
$routes->get('static/(:any)', 'MediaController::serve/$1', [
|
||||
'as' => 'media-serve',
|
||||
'namespace' => 'Modules\Media\Controllers',
|
||||
'filter' => 'allow-cors',
|
||||
]);
|
@ -1,26 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @copyright 2020 Ad Aures
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
||||
* @link https://castopod.org/
|
||||
*/
|
||||
|
||||
namespace Modules\Media\Controllers;
|
||||
|
||||
use CodeIgniter\Controller;
|
||||
use CodeIgniter\HTTP\Response;
|
||||
use Modules\Media\FileManagers\FileManagerInterface;
|
||||
|
||||
class MediaController extends Controller
|
||||
{
|
||||
public function serve(string ...$key): Response
|
||||
{
|
||||
/** @var FileManagerInterface $fileManager */
|
||||
$fileManager = service('file_manager');
|
||||
|
||||
return $fileManager->serve(implode('/', $key));
|
||||
}
|
||||
}
|
@ -5,7 +5,6 @@ declare(strict_types=1);
|
||||
namespace Modules\Media\FileManagers;
|
||||
|
||||
use CodeIgniter\Files\File;
|
||||
use CodeIgniter\HTTP\Response;
|
||||
use Exception;
|
||||
use Modules\Media\Config\Media as MediaConfig;
|
||||
|
||||
@ -131,11 +130,6 @@ class FS implements FileManagerInterface
|
||||
return is_really_writable($this->media_path_absolute());
|
||||
}
|
||||
|
||||
public function serve(string $key): Response
|
||||
{
|
||||
return redirect()->to($this->getUrl($key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefixes the absolute storage directory to the media path of a given uri
|
||||
*
|
||||
|
@ -5,7 +5,6 @@ declare(strict_types=1);
|
||||
namespace Modules\Media\FileManagers;
|
||||
|
||||
use CodeIgniter\Files\File;
|
||||
use CodeIgniter\HTTP\Response;
|
||||
|
||||
interface FileManagerInterface
|
||||
{
|
||||
@ -28,6 +27,4 @@ interface FileManagerInterface
|
||||
public function deleteAll(string $prefix, string $pattern = '*'): bool;
|
||||
|
||||
public function isHealthy(): bool;
|
||||
|
||||
public function serve(string $key): Response;
|
||||
}
|
||||
|
@ -6,11 +6,7 @@ namespace Modules\Media\FileManagers;
|
||||
|
||||
use Aws\Credentials\Credentials;
|
||||
use Aws\S3\S3Client;
|
||||
use CodeIgniter\Exceptions\PageNotFoundException;
|
||||
use CodeIgniter\Files\File;
|
||||
use CodeIgniter\HTTP\IncomingRequest;
|
||||
use CodeIgniter\HTTP\Response;
|
||||
use DateTime;
|
||||
use Exception;
|
||||
use Modules\Media\Config\Media as MediaConfig;
|
||||
|
||||
@ -39,6 +35,7 @@ class S3 implements FileManagerInterface
|
||||
'SourceFile' => $file,
|
||||
'ContentType' => $file->getMimeType(),
|
||||
'CacheControl' => 'max-age=' . YEAR,
|
||||
'ACL' => 'public-read',
|
||||
]);
|
||||
|
||||
// delete file after storage in s3
|
||||
@ -63,7 +60,7 @@ class S3 implements FileManagerInterface
|
||||
|
||||
public function getUrl(string $key): string
|
||||
{
|
||||
return media_url((string) route_to('media-serve', $key));
|
||||
return media_url($this->prefixKey($key));
|
||||
}
|
||||
|
||||
public function rename(string $oldKey, string $newKey): bool
|
||||
@ -74,6 +71,7 @@ class S3 implements FileManagerInterface
|
||||
'Bucket' => $this->config->s3['bucket'],
|
||||
'CopySource' => $this->config->s3['bucket'] . '/' . $this->prefixKey($oldKey),
|
||||
'Key' => $this->prefixKey($newKey),
|
||||
'ACL' => 'public-read',
|
||||
]);
|
||||
} catch (Exception) {
|
||||
return false;
|
||||
@ -182,92 +180,6 @@ class S3 implements FileManagerInterface
|
||||
return true;
|
||||
}
|
||||
|
||||
public function serve(string $key): Response
|
||||
{
|
||||
if ($this->config->s3['serveWithRedirect']) {
|
||||
return $this->servePresignedRequest($key);
|
||||
}
|
||||
|
||||
return $this->serveProxy($key);
|
||||
}
|
||||
|
||||
private function serveProxy(string $key): Response
|
||||
{
|
||||
/** @var IncomingRequest $incomingRequest */
|
||||
$incomingRequest = service('request');
|
||||
|
||||
/** @var Response $response */
|
||||
$response = service('response');
|
||||
|
||||
$s3Request = [
|
||||
'Bucket' => $this->config->s3['bucket'],
|
||||
'Key' => $this->prefixKey($key),
|
||||
];
|
||||
|
||||
foreach ($incomingRequest->headers() as $header) {
|
||||
$s3Request[$header->getName()] = $header->getValue();
|
||||
}
|
||||
|
||||
try {
|
||||
$result = $this->s3->getObject($s3Request);
|
||||
} catch (Exception) {
|
||||
throw new PageNotFoundException();
|
||||
}
|
||||
|
||||
// Remove Cache-Control header before redefining it
|
||||
header_remove('Cache-Control');
|
||||
|
||||
$response->setStatusCode($result['@metadata']['statusCode']);
|
||||
|
||||
// set same headers as response from s3
|
||||
foreach ($result['@metadata']['headers'] as $headerName => $headerValue) {
|
||||
$response->setHeader($headerName, $headerValue);
|
||||
}
|
||||
|
||||
return $response->setBody((string) $result->get('Body')->getContents());
|
||||
}
|
||||
|
||||
private function servePresignedRequest(string $key): Response
|
||||
{
|
||||
$cacheName = 'object_presigned_uri_' . str_replace('/', '-', $key) . '_' . $this->config->s3['bucket'];
|
||||
if (! $found = cache($cacheName)) {
|
||||
$cmd = $this->s3->getCommand('GetObject', [
|
||||
'Bucket' => $this->config->s3['bucket'],
|
||||
'Key' => $this->prefixKey($key),
|
||||
]);
|
||||
|
||||
$request = $this->s3->createPresignedRequest($cmd, '+1 day');
|
||||
|
||||
$found = (string) $request->getUri();
|
||||
|
||||
cache()
|
||||
->save($cacheName, $found, DAY);
|
||||
}
|
||||
|
||||
$cacheOptions = [
|
||||
'max-age' => DAY,
|
||||
'etag' => md5($found),
|
||||
'public' => true,
|
||||
];
|
||||
|
||||
if (cache()->getMetaData($cacheName)) {
|
||||
$lastModifiedTimestamp = cache()
|
||||
->getMetaData($cacheName)['mtime'];
|
||||
$lastModified = new DateTime();
|
||||
$lastModified->setTimestamp($lastModifiedTimestamp);
|
||||
$cacheOptions['last-modified'] = $lastModified->format(DATE_RFC7231);
|
||||
}
|
||||
|
||||
/** @var Response $response */
|
||||
$response = service('response');
|
||||
|
||||
// Remove Cache-Control header before redefining it
|
||||
header_remove('Cache-Control');
|
||||
|
||||
return $response->setCache($cacheOptions)
|
||||
->redirect($found);
|
||||
}
|
||||
|
||||
private function prefixKey(string $key): string
|
||||
{
|
||||
if ($this->config->s3['keyPrefix'] === '') {
|
||||
|
Loading…
x
Reference in New Issue
Block a user