object storage related updates
This commit is contained in:
@@ -21,8 +21,13 @@ async function bootstrap() {
|
||||
const appEnv = configService.get<string>('app.env') || 'development';
|
||||
const corsOrigins = configService.get<string[]>('cors.origins') || [];
|
||||
|
||||
// Security
|
||||
app.use(helmet());
|
||||
// Security — allow cross-origin API reads from frontend/admin domains
|
||||
app.use(
|
||||
helmet({
|
||||
crossOriginResourcePolicy: { policy: 'cross-origin' },
|
||||
crossOriginOpenerPolicy: { policy: 'same-origin-allow-popups' },
|
||||
}),
|
||||
);
|
||||
app.use(cookieParser());
|
||||
|
||||
// CORS
|
||||
|
||||
@@ -16,12 +16,31 @@ export class UploadService {
|
||||
private bucket: string;
|
||||
private region: string;
|
||||
private folderPrefix: string;
|
||||
/** Endpoint used for SDK signing/calls (no /s3 path prefix). */
|
||||
private endpoint: string;
|
||||
/** Public base shown in browser URLs (may include /s3 path prefix). */
|
||||
private publicEndpoint: string;
|
||||
|
||||
constructor(private configService: ConfigService) {
|
||||
this.region = this.configService.get<string>('AWS_REGION') || 'us-east-1';
|
||||
this.bucket = this.configService.get<string>('AWS_S3_BUCKET') || '';
|
||||
this.endpoint = this.configService.get<string>('S3_ENDPOINT') || '';
|
||||
const rawEndpoint = (this.configService.get<string>('S3_ENDPOINT') || '').replace(
|
||||
/\/$/,
|
||||
'',
|
||||
);
|
||||
// Path-prefix public URL (e.g. https://re-quest.com/s3): sign against the host
|
||||
// root so SigV4 path matches what MinIO sees after nginx strips /s3.
|
||||
if (rawEndpoint.endsWith('/s3')) {
|
||||
this.publicEndpoint = rawEndpoint;
|
||||
this.endpoint = rawEndpoint.slice(0, -3);
|
||||
} else {
|
||||
this.endpoint = rawEndpoint;
|
||||
this.publicEndpoint =
|
||||
(this.configService.get<string>('S3_PUBLIC_ENDPOINT') || rawEndpoint).replace(
|
||||
/\/$/,
|
||||
'',
|
||||
);
|
||||
}
|
||||
// Use S3_FOLDER_PREFIX from env, defaults to 'development' for dev environment
|
||||
this.folderPrefix = this.configService.get<string>('S3_FOLDER_PREFIX') || 'development';
|
||||
|
||||
@@ -52,6 +71,14 @@ export class UploadService {
|
||||
this.s3Client = new S3Client(s3Config);
|
||||
}
|
||||
|
||||
/** Rewrite SDK URLs to the public /s3 path when configured. */
|
||||
private toPublicUrl(url: string): string {
|
||||
if (!this.endpoint || !this.publicEndpoint || this.endpoint === this.publicEndpoint) {
|
||||
return url;
|
||||
}
|
||||
return url.replace(this.endpoint, this.publicEndpoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the full S3 key with environment prefix
|
||||
*/
|
||||
@@ -139,11 +166,9 @@ export class UploadService {
|
||||
expiresIn: 3600, // 1 hour
|
||||
});
|
||||
|
||||
const publicUrl = `https://${this.bucket}.s3.${this.region}.amazonaws.com/${key}`;
|
||||
|
||||
return {
|
||||
uploadUrl,
|
||||
publicUrl,
|
||||
uploadUrl: this.toPublicUrl(uploadUrl),
|
||||
publicUrl: this.getPublicUrl(key),
|
||||
key,
|
||||
};
|
||||
}
|
||||
@@ -163,15 +188,17 @@ export class UploadService {
|
||||
Key: key,
|
||||
});
|
||||
|
||||
return getSignedUrl(this.s3Client, command, {
|
||||
const url = await getSignedUrl(this.s3Client, command, {
|
||||
expiresIn: 3600, // 1 hour
|
||||
});
|
||||
return this.toPublicUrl(url);
|
||||
}
|
||||
|
||||
getPublicUrl(key: string): string {
|
||||
const base = this.publicEndpoint || this.endpoint;
|
||||
// For custom S3-compatible endpoints (Contabo, MinIO, etc.)
|
||||
if (this.endpoint) {
|
||||
return `${this.endpoint}/${this.bucket}/${key}`;
|
||||
if (base) {
|
||||
return `${base}/${this.bucket}/${key}`;
|
||||
}
|
||||
// For AWS S3
|
||||
return `https://${this.bucket}.s3.${this.region}.amazonaws.com/${key}`;
|
||||
@@ -242,7 +269,7 @@ export class UploadService {
|
||||
const publicUrl = this.getPublicUrl(key);
|
||||
|
||||
return {
|
||||
uploadUrl,
|
||||
uploadUrl: this.toPublicUrl(uploadUrl),
|
||||
publicUrl,
|
||||
key,
|
||||
};
|
||||
@@ -279,7 +306,7 @@ export class UploadService {
|
||||
const publicUrl = this.getPublicUrl(key);
|
||||
|
||||
return {
|
||||
uploadUrl,
|
||||
uploadUrl: this.toPublicUrl(uploadUrl),
|
||||
publicUrl,
|
||||
key,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user