s3 service adjustment

quickly

Signed-off-by: Kenneth Obsequio <k80308392@gmail.com>
This commit is contained in:
2026-07-07 17:46:06 +08:00
parent 50763ad348
commit 0e4cd86119
3 changed files with 27 additions and 9 deletions
+1 -1
View File
@@ -180,7 +180,7 @@ exports.issueToken = async (req, res) => {
let thumbnail_url = null; let thumbnail_url = null;
if (asset.thumbnail_storage_key) { if (asset.thumbnail_storage_key) {
try { try {
thumbnail_url = await s3.getSignedDownloadUrl(asset.thumbnail_storage_key, TOKEN_TTL_SEC); thumbnail_url = await s3.getPublicUrl(asset.thumbnail_storage_key);
} catch { } catch {
// Non-fatal — thumbnail is cosmetic // Non-fatal — thumbnail is cosmetic
} }
+1 -1
View File
@@ -99,7 +99,7 @@ async function issueForAsset(asset, userId, ip) {
let thumbnail_url = null; let thumbnail_url = null;
if (asset.thumbnail_storage_key) { if (asset.thumbnail_storage_key) {
try { try {
thumbnail_url = await s3.getSignedDownloadUrl(asset.thumbnail_storage_key, TOKEN_TTL_SEC); thumbnail_url = await s3.getPublicUrl(asset.thumbnail_storage_key);
} catch { } catch {
// Non-fatal — thumbnail is cosmetic // Non-fatal — thumbnail is cosmetic
} }
+25 -7
View File
@@ -154,20 +154,38 @@ async function deleteFile(key) {
// ─── getSignedDownloadUrl ───────────────────────────────────────────────────── // ─── getSignedDownloadUrl ─────────────────────────────────────────────────────
// //
// Generates a short-lived pre-signed GET URL against whichever host // Generates a short-lived pre-signed GET URL against S3_ENDPOINT (internal —
// resolvePublicHost() picks, so the URL is resolvable from wherever the // this backend is always co-located with Garage, see docker-compose.yml).
// request is served (browser or proxy server), not just the one running // For server-side reads only (e.g. media.controller.js streamAsset piping
// Garage locally. // bytes to the browser itself) — never hand this URL to a browser directly.
//
// Must NOT be signed against S3_PUBLIC_URL: that host is fronted by
// garage-anon-proxy, which re-signs every request itself (header-based SigV4,
// real credentials) regardless of any query-string signature already present.
// A presigned URL arriving there collides with the proxy's own signature and
// Garage rejects the request (400 "Header `x-amz-date` should be signed").
// See getPublicUrl() below for the browser-facing equivalent.
// //
async function getSignedDownloadUrl(key, expiresInSeconds = 3600) { async function getSignedDownloadUrl(key, expiresInSeconds = 3600) {
const client = await getPublicClient();
return getSignedUrl( return getSignedUrl(
client, s3,
new GetObjectCommand({ Bucket: DEFAULT_BUCKET, Key: key }), new GetObjectCommand({ Bucket: DEFAULT_BUCKET, Key: key }),
{ expiresIn: expiresInSeconds } { expiresIn: expiresInSeconds }
); );
} }
// ─── getPublicUrl ─────────────────────────────────────────────────────────────
//
// Browser-facing object URL, unsigned. garage-anon-proxy (fronting
// S3_PUBLIC_URL) authenticates every request server-side with real
// credentials, so a client-side presign adds nothing but a broken request —
// see getSignedDownloadUrl() above. Use this wherever a URL is handed
// directly to the browser (e.g. thumbnail previews).
//
async function getPublicUrl(key, bucket = DEFAULT_BUCKET) {
return buildPublicUrl(key, bucket);
}
// ─── getObjectStream ──────────────────────────────────────────────────────── // ─── getObjectStream ────────────────────────────────────────────────────────
// //
// Fetches an S3 object and returns its readable stream + metadata, for use // Fetches an S3 object and returns its readable stream + metadata, for use
@@ -198,4 +216,4 @@ async function ping() {
await client.send(new HeadBucketCommand({ Bucket: DEFAULT_BUCKET })); await client.send(new HeadBucketCommand({ Bucket: DEFAULT_BUCKET }));
} }
module.exports = { uploadFile, deleteFile, getSignedDownloadUrl, getObjectStream, ping }; module.exports = { uploadFile, deleteFile, getSignedDownloadUrl, getPublicUrl, getObjectStream, ping };