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;
if (asset.thumbnail_storage_key) {
try {
thumbnail_url = await s3.getSignedDownloadUrl(asset.thumbnail_storage_key, TOKEN_TTL_SEC);
thumbnail_url = await s3.getPublicUrl(asset.thumbnail_storage_key);
} catch {
// Non-fatal — thumbnail is cosmetic
}
+1 -1
View File
@@ -99,7 +99,7 @@ async function issueForAsset(asset, userId, ip) {
let thumbnail_url = null;
if (asset.thumbnail_storage_key) {
try {
thumbnail_url = await s3.getSignedDownloadUrl(asset.thumbnail_storage_key, TOKEN_TTL_SEC);
thumbnail_url = await s3.getPublicUrl(asset.thumbnail_storage_key);
} catch {
// Non-fatal — thumbnail is cosmetic
}
+25 -7
View File
@@ -154,20 +154,38 @@ async function deleteFile(key) {
// ─── getSignedDownloadUrl ─────────────────────────────────────────────────────
//
// Generates a short-lived pre-signed GET URL against whichever host
// resolvePublicHost() picks, so the URL is resolvable from wherever the
// request is served (browser or proxy server), not just the one running
// Garage locally.
// Generates a short-lived pre-signed GET URL against S3_ENDPOINT (internal —
// this backend is always co-located with Garage, see docker-compose.yml).
// For server-side reads only (e.g. media.controller.js streamAsset piping
// 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) {
const client = await getPublicClient();
return getSignedUrl(
client,
s3,
new GetObjectCommand({ Bucket: DEFAULT_BUCKET, Key: key }),
{ 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 ────────────────────────────────────────────────────────
//
// 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 }));
}
module.exports = { uploadFile, deleteFile, getSignedDownloadUrl, getObjectStream, ping };
module.exports = { uploadFile, deleteFile, getSignedDownloadUrl, getPublicUrl, getObjectStream, ping };