fix: rework image serving

This commit is contained in:
diced 2022-10-29 22:43:42 -07:00
parent 561849ae5b
commit 8c9064fd93
No known key found for this signature in database
GPG key ID: 370BD1BA142842D1
4 changed files with 44 additions and 32 deletions

View file

@ -230,15 +230,15 @@ async function handler(req: NextApiReq, res: NextApiRes) {
if (compressionUsed) { if (compressionUsed) {
const buffer = await sharp(file.buffer).jpeg({ quality: imageCompressionPercent }).toBuffer(); const buffer = await sharp(file.buffer).jpeg({ quality: imageCompressionPercent }).toBuffer();
await datasource.save(image.file, buffer); await datasource.save(image.file, buffer);
Logger.get('image').info( Logger.get('file').info(
`User ${user.username} (${user.id}) compressed image from ${file.buffer.length} -> ${buffer.length} bytes` `User ${user.username} (${user.id}) compressed image from ${file.buffer.length} -> ${buffer.length} bytes`
); );
} else { } else {
await datasource.save(image.file, file.buffer); await datasource.save(image.file, file.buffer);
} }
Logger.get('image').info( Logger.get('file').info(
`User ${user.username} (${user.id}) uploaded an image ${image.file} (${image.id})` `User ${user.username} (${user.id}) uploaded an file ${image.file} (${image.id})`
); );
if (user.domains.length) { if (user.domains.length) {
const domain = user.domains[Math.floor(Math.random() * user.domains.length)]; const domain = user.domains[Math.floor(Math.random() * user.domains.length)];

View file

@ -26,7 +26,7 @@ async function handler(req: NextApiReq, res: NextApiRes) {
userId: user.id, userId: user.id,
}, },
}); });
Logger.get('image').info(`User ${user.username} (${user.id}) deleted ${count} files.`); Logger.get('users').info(`User ${user.username} (${user.id}) deleted ${count} files.`);
return res.json({ count }); return res.json({ count });
} else { } else {
@ -40,7 +40,7 @@ async function handler(req: NextApiReq, res: NextApiRes) {
await datasource.delete(image.file); await datasource.delete(image.file);
Logger.get('image').info( Logger.get('users').info(
`User ${user.username} (${user.id}) deleted an image ${image.file} (${image.id})` `User ${user.username} (${user.id}) deleted an image ${image.file} (${image.id})`
); );

View file

@ -51,7 +51,7 @@ async function handler(req: NextApiReq, res: NextApiRes) {
userId: deleteUser.id, userId: deleteUser.id,
}, },
}); });
Logger.get('image').info( Logger.get('users').info(
`User ${user.username} (${user.id}) deleted ${count} files of user ${deleteUser.username} (${deleteUser.id})` `User ${user.username} (${user.id}) deleted ${count} files of user ${deleteUser.username} (${deleteUser.id})`
); );
} }

View file

@ -120,11 +120,14 @@ async function start() {
}, },
}); });
if (!image) await rawFile(req, res, nextServer, params.id); if (!image) return rawFile(req, res, nextServer, params.id);
else { else {
if (image.password) return redirect(res, `/view/${image.file}`); const failed = await preImage(image, prisma);
else if (image.embed) await handle(req, res); if (failed) return nextServer.render404(req, res as ServerResponse);
else await fileDb(req, res, nextServer, prisma, handle, image);
if (image.password || image.embed || image.mimetype.startsWith('text/'))
return redirect(res, `/view/${image.file}`);
else return fileDb(req, res, nextServer, handle, image);
} }
}); });
@ -139,6 +142,9 @@ async function start() {
if (!image) await rawFile(req, res, nextServer, params.id); if (!image) await rawFile(req, res, nextServer, params.id);
else { else {
const failed = await preImage(image, prisma);
if (failed) return nextServer.render404(req, res as ServerResponse);
if (image.password) { if (image.password) {
res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Type', 'application/json');
res.statusCode = 403; res.statusCode = 403;
@ -187,9 +193,37 @@ async function start() {
}, config.core.invites_interval * 1000); }, config.core.invites_interval * 1000);
} }
async function preImage(image: Image, prisma: PrismaClient) {
if (image.expires_at && image.expires_at < new Date()) {
await datasource.delete(image.file);
await prisma.image.delete({ where: { id: image.id } });
Logger.get('file').info(`File ${image.file} expired and was deleted.`);
return true;
}
const nImage = await prisma.image.update({
where: { id: image.id },
data: { views: { increment: 1 } },
});
if (nImage.maxViews && nImage.views >= nImage.maxViews) {
await datasource.delete(image.file);
await prisma.image.delete({ where: { id: image.id } });
Logger.get('file').info(`File ${image.file} has been deleted due to max views (${nImage.maxViews})`);
return true;
}
return false;
}
async function rawFile(req: IncomingMessage, res: OutgoingMessage, nextServer: NextServer, id: string) { async function rawFile(req: IncomingMessage, res: OutgoingMessage, nextServer: NextServer, id: string) {
const data = await datasource.get(id); const data = await datasource.get(id);
if (!data) return nextServer.render404(req, res as ServerResponse); if (!data) return nextServer.render404(req, res as ServerResponse);
const mimetype = await guess(extname(id)); const mimetype = await guess(extname(id));
const size = await datasource.size(id); const size = await datasource.size(id);
@ -205,37 +239,15 @@ async function fileDb(
req: IncomingMessage, req: IncomingMessage,
res: OutgoingMessage, res: OutgoingMessage,
nextServer: NextServer, nextServer: NextServer,
prisma: PrismaClient,
handle: RequestHandler, handle: RequestHandler,
image: Image image: Image
) { ) {
if (image.expires_at && image.expires_at < new Date()) {
await datasource.delete(image.file);
await prisma.image.delete({ where: { id: image.id } });
return nextServer.render404(req, res as ServerResponse);
}
const ext = image.file.split('.').pop(); const ext = image.file.split('.').pop();
if (Object.keys(exts).includes(ext)) return handle(req, res as ServerResponse); if (Object.keys(exts).includes(ext)) return handle(req, res as ServerResponse);
const data = await datasource.get(image.file); const data = await datasource.get(image.file);
if (!data) return nextServer.render404(req, res as ServerResponse); if (!data) return nextServer.render404(req, res as ServerResponse);
const nImage = await prisma.image.update({
where: { id: image.id },
data: { views: { increment: 1 } },
});
if (nImage.maxViews && nImage.views >= nImage.maxViews) {
await datasource.delete(image.file);
await prisma.image.delete({ where: { id: image.id } });
Logger.get('image').info(`Image ${image.file} has been deleted due to max views (${nImage.maxViews})`);
return nextServer.render404(req, res as ServerResponse);
}
const size = await datasource.size(image.file); const size = await datasource.size(image.file);
res.setHeader('Content-Type', image.mimetype); res.setHeader('Content-Type', image.mimetype);