Allow inline video attachment previews
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { Readable } from "node:stream";
|
||||
import type { IncomingMessage } from "node:http";
|
||||
import express from "express";
|
||||
import request from "supertest";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
@@ -190,6 +191,13 @@ function makeAttachment(contentType: string, originalFilename: string) {
|
||||
};
|
||||
}
|
||||
|
||||
function parseBinaryResponse(res: IncomingMessage, callback: (error: Error | null, body?: Buffer) => void) {
|
||||
const chunks: Buffer[] = [];
|
||||
res.on("data", (chunk) => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)));
|
||||
res.on("end", () => callback(null, Buffer.concat(chunks)));
|
||||
res.on("error", callback);
|
||||
}
|
||||
|
||||
describe("normalizeIssueAttachmentMaxBytes", () => {
|
||||
it("keeps the process-level attachment cap as the final cap", async () => {
|
||||
const previous = process.env.PAPERCLIP_ATTACHMENT_MAX_BYTES;
|
||||
@@ -362,7 +370,10 @@ describe("issue attachment routes", () => {
|
||||
mockIssueService.getAttachmentById.mockResolvedValue(makeAttachment("text/html", "report.html"));
|
||||
|
||||
const app = await createApp(storage);
|
||||
const res = await request(app).get("/api/attachments/attachment-1/content");
|
||||
const res = await request(app)
|
||||
.get("/api/attachments/attachment-1/content")
|
||||
.buffer(true)
|
||||
.parse(parseBinaryResponse);
|
||||
|
||||
expect(res.status).toBe(200);
|
||||
expect([
|
||||
|
||||
@@ -35,6 +35,7 @@ export const DEFAULT_ALLOWED_TYPES: readonly string[] = [
|
||||
"video/mp4",
|
||||
"video/webm",
|
||||
"video/quicktime",
|
||||
"video/x-m4v",
|
||||
];
|
||||
|
||||
export const DEFAULT_ATTACHMENT_CONTENT_TYPE = "application/octet-stream";
|
||||
@@ -49,6 +50,7 @@ export const INLINE_ATTACHMENT_TYPES: readonly string[] = [
|
||||
"video/mp4",
|
||||
"video/webm",
|
||||
"video/quicktime",
|
||||
"video/x-m4v",
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -60,8 +60,6 @@ function makeAttachment(overrides: Partial<IssueAttachment> = {}): IssueAttachme
|
||||
createdAt: new Date("2026-06-01T00:00:00.000Z"),
|
||||
updatedAt: new Date("2026-06-01T00:00:00.000Z"),
|
||||
contentPath: "/api/attachments/attachment-1/content",
|
||||
openPath: "/api/attachments/attachment-1/content",
|
||||
downloadPath: "/api/attachments/attachment-1/content?download=1",
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
@@ -271,8 +269,6 @@ describe("IssueAttachmentsSection", () => {
|
||||
originalFilename: "report.pdf",
|
||||
contentType: "application/pdf",
|
||||
contentPath: "/api/attachments/pdf-attachment/content",
|
||||
openPath: "/api/attachments/pdf-attachment/content",
|
||||
downloadPath: "/api/attachments/pdf-attachment/content?download=1",
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
|
||||
@@ -7,6 +7,12 @@ const GENERIC_ATTACHMENT_CONTENT_TYPES = new Set([
|
||||
"application/x-binary",
|
||||
]);
|
||||
|
||||
type AttachmentPathLike = {
|
||||
contentPath: string;
|
||||
openPath?: string;
|
||||
downloadPath?: string;
|
||||
};
|
||||
|
||||
function normalizedContentType(attachment: Pick<IssueAttachment, "contentType">) {
|
||||
return attachment.contentType.toLowerCase().split(";")[0]?.trim() ?? "";
|
||||
}
|
||||
@@ -15,15 +21,11 @@ export function attachmentFilename(attachment: Pick<IssueAttachment, "id" | "ori
|
||||
return attachment.originalFilename ?? attachment.id;
|
||||
}
|
||||
|
||||
export function attachmentOpenPath(
|
||||
attachment: Pick<IssueAttachment, "contentPath" | "openPath">,
|
||||
) {
|
||||
export function attachmentOpenPath(attachment: AttachmentPathLike) {
|
||||
return attachment.openPath ?? attachment.contentPath;
|
||||
}
|
||||
|
||||
export function attachmentDownloadPath(
|
||||
attachment: Pick<IssueAttachment, "contentPath" | "downloadPath">,
|
||||
) {
|
||||
export function attachmentDownloadPath(attachment: AttachmentPathLike) {
|
||||
return attachment.downloadPath ?? `${attachment.contentPath}?download=1`;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user