0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-03-10 22:22:45 -05:00

feat(core): support custom endpoint and addressing style for S3 (#6924)

Add support for configurable S3 endpoint and addressing style (path-style/virtual-hosted)
to improve compatibility with S3-compatible storage services.

- Add forcePathStyle option to control URL addressing style
- Fix custom endpoint support implementation
- Improve URL generation logic for different configurations

Resolves: [#6920]

Signed-off-by: aiden_lu <allaher@icloud.com>
This commit is contained in:
aiden 2025-01-08 08:46:54 +08:00 committed by GitHub
parent b3a12e4a2a
commit 39cef8ea47
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 33 additions and 1 deletions

View file

@ -0,0 +1,5 @@
---
"@logto/core": patch
---
support custom endpoint and addressing style for S3

View file

@ -19,7 +19,7 @@ export const buildUploadFile = (config: StorageProviderData): UploadFile | Uploa
return storage.uploadFile;
}
const { endpoint, bucket, accessKeyId, accessSecretKey, region } = config;
const { endpoint, bucket, accessKeyId, forcePathStyle, accessSecretKey, region } = config;
const storage = buildS3Storage({
endpoint,
@ -27,6 +27,7 @@ export const buildUploadFile = (config: StorageProviderData): UploadFile | Uploa
accessKeyId,
secretAccessKey: accessSecretKey,
region,
forcePathStyle,
});
return storage.uploadFile;

View file

@ -16,6 +16,7 @@ type BuildS3StorageParameters = {
secretAccessKey: string;
region?: string;
endpoint?: string;
forcePathStyle?: boolean;
};
export const buildS3Storage = ({
@ -24,6 +25,7 @@ export const buildS3Storage = ({
secretAccessKey,
region,
endpoint,
forcePathStyle,
}: BuildS3StorageParameters) => {
if (!region && !endpoint) {
throw new Error('Either region or endpoint must be provided');
@ -35,6 +37,7 @@ export const buildS3Storage = ({
const client = new S3Client({
region: finalRegion,
endpoint,
forcePathStyle,
credentials: {
accessKeyId,
secretAccessKey,
@ -56,6 +59,28 @@ export const buildS3Storage = ({
return { url: `${publicUrl}/${objectKey}` };
}
if (endpoint) {
// Custom endpoint URL construction
if (forcePathStyle) {
// Path-style URL: https://endpoint/bucket/key
return {
url: `${endpoint}/${bucket}/${objectKey}`,
};
}
// Virtual-hosted style URL: https://bucket.endpoint/key
return {
url: `${endpoint.replace(/^(https?:\/\/)/, `$1${bucket}.`)}/${objectKey}`,
};
}
// AWS S3 standard URL construction
if (forcePathStyle) {
// Path-style URL: https://s3.region.amazonaws.com/bucket/key
return {
url: `https://s3.${finalRegion}.amazonaws.com/${bucket}/${objectKey}`,
};
}
// Virtual-hosted style URL: https://bucket.s3.region.amazonaws.com/key
return {
url: `https://${bucket}.s3.${finalRegion}.amazonaws.com/${objectKey}`,
};

View file

@ -44,6 +44,7 @@ export const storageProviderDataGuard = z.discriminatedUnion('provider', [
endpoint: z.string().optional(),
region: z.string().optional(),
bucket: z.string(),
forcePathStyle: z.boolean().optional(),
accessKeyId: z.string(),
accessSecretKey: z.string(),
...basicConfig,