@@ -1,11 +1,16 @@
|
||||
import { URL } from 'node:url';
|
||||
import * as http from 'node:http';
|
||||
import * as https from 'node:https';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import S3 from 'aws-sdk/clients/s3.js';
|
||||
import { DeleteObjectCommand, S3Client } from '@aws-sdk/client-s3';
|
||||
import { Upload } from '@aws-sdk/lib-storage';
|
||||
import { NodeHttpHandler, NodeHttpHandlerOptions } from '@aws-sdk/node-http-handler';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { Config } from '@/config.js';
|
||||
import type { Meta } from '@/models/entities/Meta.js';
|
||||
import { HttpRequestService } from '@/core/HttpRequestService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import type { DeleteObjectCommandInput, PutObjectCommandInput } from '@aws-sdk/client-s3';
|
||||
|
||||
@Injectable()
|
||||
export class S3Service {
|
||||
@@ -18,25 +23,47 @@ export class S3Service {
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public getS3(meta: Meta) {
|
||||
public getS3Client(meta: Meta): S3Client {
|
||||
const u = meta.objectStorageEndpoint
|
||||
? `${meta.objectStorageUseSSL ? 'https://' : 'http://'}${meta.objectStorageEndpoint}`
|
||||
: `${meta.objectStorageUseSSL ? 'https://' : 'http://'}example.net`;
|
||||
? `${meta.objectStorageUseSSL ? 'https' : 'http'}://${meta.objectStorageEndpoint}`
|
||||
: `${meta.objectStorageUseSSL ? 'https' : 'http'}://example.net`; // dummy url to select http(s) agent
|
||||
|
||||
return new S3({
|
||||
endpoint: meta.objectStorageEndpoint && meta.objectStorageEndpoint.length > 0
|
||||
? meta.objectStorageEndpoint
|
||||
: undefined,
|
||||
accessKeyId: meta.objectStorageAccessKey!,
|
||||
secretAccessKey: meta.objectStorageSecretKey!,
|
||||
const agent = this.httpRequestService.getAgentByUrl(new URL(u), !meta.objectStorageUseProxy);
|
||||
const handlerOption: NodeHttpHandlerOptions = {};
|
||||
if (meta.objectStorageUseSSL) {
|
||||
handlerOption.httpsAgent = agent as https.Agent;
|
||||
} else {
|
||||
handlerOption.httpAgent = agent as http.Agent;
|
||||
}
|
||||
|
||||
return new S3Client({
|
||||
endpoint: meta.objectStorageEndpoint ? u : undefined,
|
||||
credentials: (meta.objectStorageAccessKey !== null && meta.objectStorageSecretKey !== null) ? {
|
||||
accessKeyId: meta.objectStorageAccessKey,
|
||||
secretAccessKey: meta.objectStorageSecretKey,
|
||||
} : undefined,
|
||||
region: meta.objectStorageRegion ?? undefined,
|
||||
sslEnabled: meta.objectStorageUseSSL,
|
||||
s3ForcePathStyle: !meta.objectStorageEndpoint // AWS with endPoint omitted
|
||||
? false
|
||||
: meta.objectStorageS3ForcePathStyle,
|
||||
httpOptions: {
|
||||
agent: this.httpRequestService.getAgentByUrl(new URL(u), !meta.objectStorageUseProxy),
|
||||
},
|
||||
tls: meta.objectStorageUseSSL,
|
||||
forcePathStyle: meta.objectStorageEndpoint ? meta.objectStorageS3ForcePathStyle : false, // AWS with endPoint omitted
|
||||
requestHandler: new NodeHttpHandler(handlerOption),
|
||||
});
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public async upload(meta: Meta, input: PutObjectCommandInput) {
|
||||
const client = this.getS3Client(meta);
|
||||
return new Upload({
|
||||
client,
|
||||
params: input,
|
||||
partSize: (client.config.endpoint && (await client.config.endpoint()).hostname === 'storage.googleapis.com')
|
||||
? 500 * 1024 * 1024
|
||||
: 8 * 1024 * 1024,
|
||||
}).done();
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public delete(meta: Meta, input: DeleteObjectCommandInput) {
|
||||
const client = this.getS3Client(meta);
|
||||
return client.send(new DeleteObjectCommand(input));
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user