mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-18 13:35:42 +09:00
fix(api): resolve s3 copy source under endpoint path (#3422)
This commit is contained in:
1 parent
ab19c0d1ac
commit
8bda151596
4 files changed
+201
-1
No files matched your search
@@ -115,6 +115,13 @@ const REJECTED_SERVER_SIDE_COPY_ERRORS = new Set([
|
||||
'MethodNotAllowed',
|
||||
]);
|
||||
|
||||
function encodedEndpointPath(endpoint: string): Array<string> {
|
||||
return (URL.parse(endpoint)?.pathname ?? '')
|
||||
.split('/')
|
||||
.filter((segment) => segment !== '')
|
||||
.map((segment) => encodeURIComponent(decodeURIComponent(segment)));
|
||||
}
|
||||
|
||||
function isRejectedServerSideCopy(error: unknown): boolean {
|
||||
return (
|
||||
error instanceof S3ServiceException &&
|
||||
@@ -126,6 +133,7 @@ export class StorageService implements IStorageService {
|
||||
private readonly client: S3Client;
|
||||
private readonly presignClient: S3Client;
|
||||
private readonly provider: S3ProviderSettings;
|
||||
private readonly endpointPath: Array<string>;
|
||||
|
||||
constructor(provider?: S3ProviderSettings) {
|
||||
this.provider = provider ?? {
|
||||
@@ -136,6 +144,7 @@ export class StorageService implements IStorageService {
|
||||
accessKeyId: Config.s3.accessKeyId,
|
||||
secretAccessKey: Config.s3.secretAccessKey,
|
||||
};
|
||||
this.endpointPath = encodedEndpointPath(this.provider.endpoint);
|
||||
this.client = buildPooledS3Client({
|
||||
endpoint: this.provider.endpoint,
|
||||
region: this.provider.region,
|
||||
@@ -492,7 +501,7 @@ export class StorageService implements IStorageService {
|
||||
new CopyObjectCommand({
|
||||
Bucket: destinationBucket,
|
||||
Key: destinationKey,
|
||||
CopySource: `${encodeURIComponent(sourceBucket)}/${sourceKey.split('/').map(encodeURIComponent).join('/')}`,
|
||||
CopySource: this.copySource(sourceBucket, sourceKey),
|
||||
ContentType: newContentType,
|
||||
MetadataDirective: newContentType ? 'REPLACE' : undefined,
|
||||
}),
|
||||
@@ -508,6 +517,14 @@ export class StorageService implements IStorageService {
|
||||
}
|
||||
}
|
||||
|
||||
private copySource(bucket: string, key: string): string {
|
||||
const encodedBucket = encodeURIComponent(bucket);
|
||||
const location = this.provider.forcePathStyle
|
||||
? [...this.endpointPath, encodedBucket]
|
||||
: [encodedBucket, ...this.endpointPath];
|
||||
return [...location, ...key.split('/').map(encodeURIComponent)].join('/');
|
||||
}
|
||||
|
||||
private async copyObjectThroughApi(
|
||||
{
|
||||
sourceBucket,
|
||||
|
||||
Reference in new issue
Block a user