fix: Signed file urls not returning inline content disposition
This commit is contained in:
@@ -72,34 +72,32 @@ router.get(
|
|||||||
async (ctx: APIContext<T.FilesGetReq>) => {
|
async (ctx: APIContext<T.FilesGetReq>) => {
|
||||||
const actor = ctx.state.auth.user;
|
const actor = ctx.state.auth.user;
|
||||||
const key = getKeyFromContext(ctx);
|
const key = getKeyFromContext(ctx);
|
||||||
|
const forceDownload = !!ctx.input.query.download;
|
||||||
const isSignedRequest = !!ctx.input.query.sig;
|
const isSignedRequest = !!ctx.input.query.sig;
|
||||||
const { isPublicBucket, fileName } = AttachmentHelper.parseKey(key);
|
const { isPublicBucket, fileName } = AttachmentHelper.parseKey(key);
|
||||||
const skipAuthorize = isPublicBucket || isSignedRequest;
|
const skipAuthorize = isPublicBucket || isSignedRequest;
|
||||||
const cacheHeader = "max-age=604800, immutable";
|
const cacheHeader = "max-age=604800, immutable";
|
||||||
|
let contentType =
|
||||||
|
(fileName ? mime.lookup(fileName) : undefined) ||
|
||||||
|
"application/octet-stream";
|
||||||
|
|
||||||
if (skipAuthorize) {
|
if (!skipAuthorize) {
|
||||||
ctx.set("Cache-Control", cacheHeader);
|
|
||||||
ctx.set(
|
|
||||||
"Content-Type",
|
|
||||||
(fileName ? mime.lookup(fileName) : undefined) ||
|
|
||||||
"application/octet-stream"
|
|
||||||
);
|
|
||||||
ctx.attachment(fileName);
|
|
||||||
} else {
|
|
||||||
const attachment = await Attachment.findOne({
|
const attachment = await Attachment.findOne({
|
||||||
where: { key },
|
where: { key },
|
||||||
rejectOnEmpty: true,
|
rejectOnEmpty: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
authorize(actor, "read", attachment);
|
authorize(actor, "read", attachment);
|
||||||
|
contentType = attachment.contentType;
|
||||||
ctx.set("Cache-Control", cacheHeader);
|
|
||||||
ctx.set("Content-Type", attachment.contentType);
|
|
||||||
ctx.attachment(attachment.name, {
|
|
||||||
type: FileStorage.getContentDisposition(attachment.contentType),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx.set("Cache-Control", cacheHeader);
|
||||||
|
ctx.set("Content-Type", contentType);
|
||||||
|
ctx.attachment(fileName, {
|
||||||
|
type: forceDownload
|
||||||
|
? "attachment"
|
||||||
|
: FileStorage.getContentDisposition(contentType),
|
||||||
|
});
|
||||||
|
|
||||||
// Handle byte range requests
|
// Handle byte range requests
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests
|
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests
|
||||||
const stats = await (FileStorage as LocalStorage).stat(key);
|
const stats = await (FileStorage as LocalStorage).stat(key);
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ export const FilesGetSchema = z.object({
|
|||||||
.optional()
|
.optional()
|
||||||
.transform((val) => (val ? ValidateKey.sanitize(val) : undefined)),
|
.transform((val) => (val ? ValidateKey.sanitize(val) : undefined)),
|
||||||
sig: z.string().optional(),
|
sig: z.string().optional(),
|
||||||
|
download: z.string().optional(),
|
||||||
})
|
})
|
||||||
.refine((obj) => !(isEmpty(obj.key) && isEmpty(obj.sig)), {
|
.refine((obj) => !(isEmpty(obj.key) && isEmpty(obj.sig)), {
|
||||||
message: "One of key or sig is required",
|
message: "One of key or sig is required",
|
||||||
|
|||||||
Reference in New Issue
Block a user