Track HiveGrid Cloud planning reference
This commit is contained in:
1 parent
b3d5ea6764
commit
e341c5938a
5784 files changed
+1104929
-3
No files matched your search
@@ -0,0 +1,57 @@
|
||||
// P4 Files (AK-P4a) §6 — web-side presigned download URL builder for the
|
||||
// auth-proxy media route. Bucket stays private (AD-23); the proxy redirects an
|
||||
// authorized request to a short-lived signed URL. Reuses the shared SigV4
|
||||
// signer from @toolctrl/storage (no @aws-sdk/s3-request-presigner dependency).
|
||||
|
||||
import { loadRequiredWebConfig } from "@toolctrl/config";
|
||||
import { createS3SignedUrlAdapter, createSigV4DownloadSigner, StorageAdapterError } from "@toolctrl/storage";
|
||||
import { resolveStorageBucket } from "./storageService";
|
||||
|
||||
export const MEDIA_SIGNED_URL_TTL_SECONDS = 300;
|
||||
|
||||
function sanitizeFilename(filename: string): string {
|
||||
// Strip quotes/control chars so the value is safe inside a Content-Disposition header.
|
||||
return filename.replace(/["\\\r\n]/g, "").slice(0, 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a short-lived (default 300s) presigned GET URL for an object in the
|
||||
* private files bucket. `filename` (optional) sets an inline Content-Disposition
|
||||
* so the browser shows a sensible name on download.
|
||||
*/
|
||||
export async function createMediaDownloadUrl({
|
||||
key,
|
||||
filename,
|
||||
ttlSeconds = MEDIA_SIGNED_URL_TTL_SECONDS,
|
||||
}: {
|
||||
key: string;
|
||||
filename?: string;
|
||||
ttlSeconds?: number;
|
||||
}): Promise<string> {
|
||||
const { storage } = loadRequiredWebConfig();
|
||||
const bucket = resolveStorageBucket();
|
||||
const adapter = createS3SignedUrlAdapter({
|
||||
bucket,
|
||||
downloadSigner: createSigV4DownloadSigner({
|
||||
endpoint: storage.endpoint ?? "",
|
||||
region: storage.region ?? "",
|
||||
bucket,
|
||||
accessKeyId: storage.accessKeyId ?? "",
|
||||
secretAccessKey: storage.secretAccessKey ?? "",
|
||||
sessionToken: storage.sessionToken,
|
||||
forcePathStyle: storage.forcePathStyle === undefined ? undefined : storage.forcePathStyle.toLowerCase() === "true",
|
||||
}),
|
||||
uploadSigner: () => {
|
||||
throw new StorageAdapterError("signed_upload_failed", "Signed upload URLs are not supported by the media proxy.", {
|
||||
operation: "createSignedUploadUrl",
|
||||
bucket,
|
||||
});
|
||||
},
|
||||
});
|
||||
const result = await adapter.createSignedDownloadUrl({
|
||||
key,
|
||||
expiresInSeconds: ttlSeconds,
|
||||
...(filename ? { responseContentDisposition: `inline; filename="${sanitizeFilename(filename)}"` } : {}),
|
||||
});
|
||||
return result.url;
|
||||
}
|
||||
Reference in new issue
Block a user