feat: add content-length headers

This commit is contained in:
dicedtomato 2022-07-15 17:20:24 +00:00 committed by GitHub
parent 786e6d5799
commit 2f0af385c7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 55 additions and 5 deletions

View file

@ -5,6 +5,7 @@ export abstract class Datasource {
public abstract save(file: string, data: Buffer): Promise<void>;
public abstract delete(file: string): Promise<void>;
public abstract size(file: string): Promise<number>;
public abstract get(file: string): Readable | Promise<Readable>;
public abstract size(): Promise<number>;
public abstract fullSize(): Promise<number>;
}

View file

@ -29,7 +29,13 @@ export class Local extends Datasource {
}
}
public async size(): Promise<number> {
public async size(file: string): Promise<number> {
const stats = await stat(join(process.cwd(), this.path, file));
return stats.size;
}
public async fullSize(): Promise<number> {
const files = await readdir(this.path);
let size = 0;

View file

@ -37,7 +37,16 @@ export class S3 extends Datasource {
});
}
public async size(): Promise<number> {
public size(file: string): Promise<number> {
return new Promise((res, rej) => {
this.s3.statObject(this.config.bucket, file, (err, stat) => {
if (err) rej(err);
else res(stat.size);
});
});
}
public async fullSize(): Promise<number> {
return new Promise((res, rej) => {
const objects = this.s3.listObjectsV2(this.config.bucket, '', true);
let size = 0;

View file

@ -139,6 +139,7 @@ class SwiftContainer {
body: data,
});
}
public async deleteObject(name: string): Promise<any> {
const auth = await this.authenticate();
@ -147,8 +148,10 @@ class SwiftContainer {
headers: this.generateHeaders(auth.token),
});
}
public async getObject(name: string): Promise<Readable> {
const auth = await this.authenticate();
const arrayBuffer = await fetch(`${auth.swiftURL}/${this.options.credentials.container}/${name}`, {
method: 'GET',
headers: this.generateHeaders(auth.token, { Accept: '*/*' }),
@ -156,6 +159,15 @@ class SwiftContainer {
return Readable.from(Buffer.from(arrayBuffer));
}
public async headObject(name: string): Promise<any> {
const auth = await this.authenticate();
return fetch(`${auth.swiftURL}/${this.options.credentials.container}/${name}`, {
method: 'HEAD',
headers: this.generateHeaders(auth.token),
});
}
}
export class Swift extends Datasource {
@ -164,6 +176,7 @@ export class Swift extends Datasource {
public constructor(public config: ConfigSwiftDatasource) {
super();
console.log(config);
this.container = new SwiftContainer({
auth_endpoint_url: config.auth_endpoint,
credentials: {
@ -201,7 +214,17 @@ export class Swift extends Datasource {
}
}
public async size(): Promise<number> {
public async size(file: string): Promise<number> {
try {
const head = await this.container.headObject(file);
return head.headers.get('content-length') || 0;
} catch {
return 0;
}
}
public async fullSize(): Promise<number> {
return this.container
.listObjects()
.then((objects) => objects.reduce((acc, object) => acc + object.bytes, 0))

View file

@ -22,6 +22,7 @@ start();
async function start() {
const c = await import('../lib/config.js');
// @ts-ignore
config = c.default.default;
const d = await import('../lib/datasource.js');
@ -134,7 +135,10 @@ async function rawFile(
const data = await datasource.get(id);
if (!data) return nextServer.render404(req, res as ServerResponse);
const mimetype = mimes[extname(id)] ?? 'application/octet-stream';
const size = await datasource.size(id);
res.setHeader('Content-Type', mimetype);
res.setHeader('Content-Length', size);
data.pipe(res);
data.on('error', () => nextServer.render404(req, res as ServerResponse));
@ -151,7 +155,11 @@ async function rawFileDb(
const data = await datasource.get(image.file);
if (!data) return nextServer.render404(req, res as ServerResponse);
const size = await datasource.size(image.file);
res.setHeader('Content-Type', image.mimetype);
res.setHeader('Content-Length', size);
data.pipe(res);
data.on('error', () => nextServer.render404(req, res as ServerResponse));
data.on('end', () => res.end());
@ -176,7 +184,10 @@ async function fileDb(
const data = await datasource.get(image.file);
if (!data) return this.nextServer.render404(req, res as ServerResponse);
const size = await datasource.size(image.file);
res.setHeader('Content-Type', image.mimetype);
res.setHeader('Content-Length', size);
data.pipe(res);
data.on('error', () => nextServer.render404(req, res as ServerResponse));
data.on('end', () => res.end());

View file

@ -44,7 +44,7 @@ export function bytesToRead(bytes: number) {
export async function getStats(prisma: PrismaClient, datasource: Datasource) {
const size = await datasource.size();
const size = await datasource.fullSize();
const byUser = await prisma.image.groupBy({
by: ['userId'],
_count: {