fix(api): honour the configured S3 addressing on uploads (#2626)

This commit is contained in:
Hampus
2026-09-09 11:26:30 +02:00
committed by GitHub
parent bfa9bf221d
commit 9fe65d5036
4 changed files with 42 additions and 1 deletions
+5
View File
@@ -166,6 +166,11 @@ MEILI_MASTER_KEY=CHANGE_ME
#FLUXER_CLIENT_IP_HEADER_NAME=cf-connecting-ip
#FLUXER_TRUST_CLIENT_IP_HEADER=true
# How much the services write. trace, debug, info, warn, error or fatal. Every
# service names the object storage endpoint and its addressing at info on start,
# so a bucket that answers 404 is visible without raising this.
#LOG_LEVEL=debug
FLUXER_S3_ACCESS_KEY=fluxer
FLUXER_S3_SECRET_KEY=CHANGE_ME
+1
View File
@@ -14,6 +14,7 @@ x-fluxer-env: &fluxer-env
<<: *fluxer-postgres-env
FLUXER_ENV: production
NODE_ENV: production
LOG_LEVEL: ${LOG_LEVEL:-info}
FLUXER_SELF_HOSTED: "true"
FLUXER_BASE_DOMAIN: ${FLUXER_DOMAIN:?set FLUXER_DOMAIN in .env}
FLUXER_PUBLIC_SCHEME: ${FLUXER_PUBLIC_SCHEME:-https}
@@ -143,6 +143,32 @@ describe('StorageService.getPresignedUploadURL', () => {
},
);
});
it('gives both clients the configured addressing rather than pinning one to path style', async () => {
await withS3Config(
{
endpoint: 'https://s3.example.test',
presignedUrlBase: '',
forcePathStyle: false,
region: 'eu-central-1',
accessKeyId: 'fluxer',
secretAccessKey: 'fluxer-secret',
buckets: {uploads: 'fluxer-uploads'},
},
async () => {
const service = new StorageService();
const probe = service as unknown as {
client: {config: {forcePathStyle?: unknown}};
presignClient: {config: {forcePathStyle?: unknown}};
};
const resolve = async (value: unknown): Promise<unknown> =>
typeof value === 'function' ? await (value as () => Promise<unknown>)() : value;
expect(await resolve(probe.client.config.forcePathStyle)).toBe(false);
expect(await resolve(probe.presignClient.config.forcePathStyle)).toBe(false);
},
);
});
});
describe('StorageService.copyObjectWithMetadataStripping', () => {
@@ -127,7 +127,7 @@ export class StorageService implements IStorageService {
region: this.provider.region,
accessKeyId: this.provider.accessKeyId,
secretAccessKey: this.provider.secretAccessKey,
forcePathStyle: true,
forcePathStyle: this.provider.forcePathStyle,
});
this.presignClient = buildPooledS3Client({
endpoint: this.resolvePresignEndpoint(),
@@ -136,6 +136,15 @@ export class StorageService implements IStorageService {
secretAccessKey: this.provider.secretAccessKey,
forcePathStyle: this.provider.forcePathStyle,
});
Logger.info(
{
endpoint: this.provider.endpoint,
presignEndpoint: this.resolvePresignEndpoint(),
region: this.provider.region,
addressing: this.provider.forcePathStyle ? 'path' : 'virtual-host',
},
'Object storage client ready',
);
}
private resolvePresignEndpoint(): string {