mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
core: storage: use alternative client
This commit is contained in:
1 parent
65311529bd
commit
f30a39593f
1 file changed
+41
-40
@@ -20,17 +20,6 @@ import { md5, streamToBuffer } from '../utils';
|
|||||||
|
|
||||||
const logger = new Logger('storage');
|
const logger = new Logger('storage');
|
||||||
|
|
||||||
interface StorageOptions {
|
|
||||||
endPoint: string;
|
|
||||||
accessKey: string;
|
|
||||||
secretKey: string;
|
|
||||||
bucket: string;
|
|
||||||
region?: string;
|
|
||||||
pathStyle: boolean;
|
|
||||||
endPointForUser?: string;
|
|
||||||
endPointForJudge?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseAlternativeEndpointUrl(endpoint: string): (originalUrl: string) => string {
|
function parseAlternativeEndpointUrl(endpoint: string): (originalUrl: string) => string {
|
||||||
if (!endpoint) return (originalUrl) => originalUrl;
|
if (!endpoint) return (originalUrl) => originalUrl;
|
||||||
const pathonly = endpoint.startsWith('/');
|
const pathonly = endpoint.startsWith('/');
|
||||||
@@ -71,8 +60,12 @@ const convertPath = (p: string) => {
|
|||||||
class RemoteStorageService {
|
class RemoteStorageService {
|
||||||
public client: S3Client;
|
public client: S3Client;
|
||||||
public error = '';
|
public error = '';
|
||||||
public opts: StorageOptions;
|
public bucket = 'hydro';
|
||||||
private replaceWithAlternativeUrlFor: Record<'user' | 'judge', (originalUrl: string) => string>;
|
private replaceWithAlternativeUrlFor: Record<'user' | 'judge', (originalUrl: string) => string>;
|
||||||
|
private alternatives: Record<'user' | 'judge', S3Client> = {
|
||||||
|
user: null,
|
||||||
|
judge: null,
|
||||||
|
};
|
||||||
|
|
||||||
async start() {
|
async start() {
|
||||||
try {
|
try {
|
||||||
@@ -87,29 +80,35 @@ class RemoteStorageService {
|
|||||||
endPointForUser,
|
endPointForUser,
|
||||||
endPointForJudge,
|
endPointForJudge,
|
||||||
} = builtinConfig.file;
|
} = builtinConfig.file;
|
||||||
this.opts = {
|
this.bucket = bucket;
|
||||||
endPoint,
|
const base = {
|
||||||
accessKey,
|
|
||||||
secretKey,
|
|
||||||
bucket,
|
|
||||||
region,
|
region,
|
||||||
pathStyle,
|
forcePathStyle: pathStyle,
|
||||||
endPointForUser,
|
credentials: {
|
||||||
endPointForJudge,
|
accessKeyId: accessKey,
|
||||||
|
secretAccessKey: secretKey,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
this.client = new S3Client({
|
this.client = new S3Client({
|
||||||
endpoint: this.opts.endPoint,
|
endpoint: endPoint,
|
||||||
region: this.opts.region,
|
...base,
|
||||||
forcePathStyle: this.opts.pathStyle,
|
|
||||||
credentials: {
|
|
||||||
accessKeyId: this.opts.accessKey,
|
|
||||||
secretAccessKey: this.opts.secretKey,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
this.replaceWithAlternativeUrlFor = {
|
this.replaceWithAlternativeUrlFor = {
|
||||||
user: parseAlternativeEndpointUrl(this.opts.endPointForUser),
|
user: parseAlternativeEndpointUrl(endPointForUser),
|
||||||
judge: parseAlternativeEndpointUrl(this.opts.endPointForJudge),
|
judge: parseAlternativeEndpointUrl(endPointForJudge),
|
||||||
};
|
};
|
||||||
|
if (/^https?:\/\//.test(endPointForUser)) {
|
||||||
|
this.alternatives.user = new S3Client({
|
||||||
|
endpoint: endPointForUser,
|
||||||
|
...base,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (/^https?:\/\//.test(endPointForJudge)) {
|
||||||
|
this.alternatives.judge = new S3Client({
|
||||||
|
endpoint: endPointForJudge,
|
||||||
|
...base,
|
||||||
|
});
|
||||||
|
}
|
||||||
logger.success('Storage connected.');
|
logger.success('Storage connected.');
|
||||||
this.error = null;
|
this.error = null;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -124,7 +123,7 @@ class RemoteStorageService {
|
|||||||
target = convertPath(target);
|
target = convertPath(target);
|
||||||
if (typeof file === 'string') file = createReadStream(file);
|
if (typeof file === 'string') file = createReadStream(file);
|
||||||
const params: PutObjectCommandInput = {
|
const params: PutObjectCommandInput = {
|
||||||
Bucket: this.opts.bucket,
|
Bucket: this.bucket,
|
||||||
Key: target,
|
Key: target,
|
||||||
Body: file,
|
Body: file,
|
||||||
Metadata: meta,
|
Metadata: meta,
|
||||||
@@ -148,7 +147,7 @@ class RemoteStorageService {
|
|||||||
async get(target: string, path?: string) {
|
async get(target: string, path?: string) {
|
||||||
target = convertPath(target);
|
target = convertPath(target);
|
||||||
const res = await this.client.send(new GetObjectCommand({
|
const res = await this.client.send(new GetObjectCommand({
|
||||||
Bucket: this.opts.bucket,
|
Bucket: this.bucket,
|
||||||
Key: target,
|
Key: target,
|
||||||
}));
|
}));
|
||||||
if (!res.Body) throw new Error();
|
if (!res.Body) throw new Error();
|
||||||
@@ -175,12 +174,12 @@ class RemoteStorageService {
|
|||||||
else target = target.map(convertPath);
|
else target = target.map(convertPath);
|
||||||
if (typeof target === 'string') {
|
if (typeof target === 'string') {
|
||||||
return await this.client.send(new DeleteObjectCommand({
|
return await this.client.send(new DeleteObjectCommand({
|
||||||
Bucket: this.opts.bucket,
|
Bucket: this.bucket,
|
||||||
Key: target,
|
Key: target,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
return await this.client.send(new DeleteObjectsCommand({
|
return await this.client.send(new DeleteObjectsCommand({
|
||||||
Bucket: this.opts.bucket,
|
Bucket: this.bucket,
|
||||||
Delete: {
|
Delete: {
|
||||||
Objects: target.map((i) => ({ Key: i })),
|
Objects: target.map((i) => ({ Key: i })),
|
||||||
},
|
},
|
||||||
@@ -190,7 +189,7 @@ class RemoteStorageService {
|
|||||||
async getMeta(target: string) {
|
async getMeta(target: string) {
|
||||||
target = convertPath(target);
|
target = convertPath(target);
|
||||||
const res = await this.client.send(new HeadObjectCommand({
|
const res = await this.client.send(new HeadObjectCommand({
|
||||||
Bucket: this.opts.bucket,
|
Bucket: this.bucket,
|
||||||
Key: target,
|
Key: target,
|
||||||
}));
|
}));
|
||||||
return {
|
return {
|
||||||
@@ -203,8 +202,9 @@ class RemoteStorageService {
|
|||||||
|
|
||||||
async signDownloadLink(target: string, filename?: string, noExpire = false, useAlternativeEndpointFor?: 'user' | 'judge'): Promise<string> {
|
async signDownloadLink(target: string, filename?: string, noExpire = false, useAlternativeEndpointFor?: 'user' | 'judge'): Promise<string> {
|
||||||
target = convertPath(target);
|
target = convertPath(target);
|
||||||
const url = await getSignedUrl(this.client, new GetObjectCommand({
|
const client = this.alternatives[useAlternativeEndpointFor] || this.client;
|
||||||
Bucket: this.opts.bucket,
|
const url = await getSignedUrl(client, new GetObjectCommand({
|
||||||
|
Bucket: this.bucket,
|
||||||
Key: target,
|
Key: target,
|
||||||
ResponseContentDisposition: filename ? `attachment; filename="${encodeRFC5987ValueChars(filename)}"` : '',
|
ResponseContentDisposition: filename ? `attachment; filename="${encodeRFC5987ValueChars(filename)}"` : '',
|
||||||
}), {
|
}), {
|
||||||
@@ -215,13 +215,14 @@ class RemoteStorageService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async signUpload(target: string, size: number) {
|
async signUpload(target: string, size: number) {
|
||||||
const { url, fields } = await createPresignedPost(this.client, {
|
const client = this.alternatives.user || this.client;
|
||||||
Bucket: this.opts.bucket,
|
const { url, fields } = await createPresignedPost(client, {
|
||||||
|
Bucket: this.bucket,
|
||||||
Key: target,
|
Key: target,
|
||||||
Conditions: [
|
Conditions: [
|
||||||
{ $key: target },
|
{ $key: target },
|
||||||
{ acl: 'public-read' },
|
{ acl: 'public-read' },
|
||||||
{ bucket: this.opts.bucket },
|
{ bucket: this.bucket },
|
||||||
['content-length-range', size - 50, size + 50],
|
['content-length-range', size - 50, size + 50],
|
||||||
],
|
],
|
||||||
Fields: {
|
Fields: {
|
||||||
@@ -239,7 +240,7 @@ class RemoteStorageService {
|
|||||||
src = convertPath(src);
|
src = convertPath(src);
|
||||||
target = convertPath(target);
|
target = convertPath(target);
|
||||||
return await this.client.send(new CopyObjectCommand({
|
return await this.client.send(new CopyObjectCommand({
|
||||||
Bucket: this.opts.bucket,
|
Bucket: this.bucket,
|
||||||
Key: target,
|
Key: target,
|
||||||
CopySource: src,
|
CopySource: src,
|
||||||
}));
|
}));
|
||||||
|
|||||||
Reference in new issue
Block a user