From f6ce2f127e159e1ceb64a4b30ca9c757f601a35e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8F=B6=E8=88=9F?= Date: Wed, 22 Jul 2026 23:24:28 +0800 Subject: [PATCH] fix: support S3-compatible services (MinIO) - Add service:'s3' to AwsClient to fix ReadableStream signing - Add S3_PROTOCOL config (default: https) - Add S3_TYPE config for virtual-hosted vs path-style URLs - Read S3_REGION from env (was declared in docker-compose but unused) --- .env.example | 6 +++++- docker-compose.example.yml | 8 +++++--- src-server/utils/config.ts | 3 +++ src-server/utils/s3.ts | 8 ++++++-- 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/.env.example b/.env.example index 8586159..3b63a2e 100644 --- a/.env.example +++ b/.env.example @@ -17,5 +17,9 @@ S3_ACCESS_KEY_ID= S3_SECRET_ACCESS_KEY= S3_ENDPOINT= S3_BUCKET= +S3_REGION=us-east-1 +# For self hosted s3 compatiable service, like minio +S3_PROTOCOL=https +S3_TYPE=virtual-hosted -SEARXNG_URL= \ No newline at end of file +SEARXNG_URL= diff --git a/docker-compose.example.yml b/docker-compose.example.yml index 060b82f..e09ba61 100644 --- a/docker-compose.example.yml +++ b/docker-compose.example.yml @@ -29,8 +29,10 @@ services: S3_ACCESS_KEY_ID: update-this S3_SECRET_ACCESS_KEY: update-this S3_ENDPOINT: update-this - S3_REGION: update-this S3_BUCKET: update-this + S3_REGION: update-this + S3_PROTOCOL: https + S3_TYPE: virtual-hosted SEARXNG_URL: update-this depends_on: @@ -49,7 +51,7 @@ services: environment: SERVER_URL: http://server:3000 ZERO_CACHE_URL: http://zero-cache:4848 - + zero-cache: image: rocicorp/zero:0.26.1 environment: @@ -84,4 +86,4 @@ configs: CREATE DATABASE zero; \c app; - CREATE EXTENSION IF NOT EXISTS zhparser; \ No newline at end of file + CREATE EXTENSION IF NOT EXISTS zhparser; diff --git a/src-server/utils/config.ts b/src-server/utils/config.ts index 1f044df..58d6e4f 100644 --- a/src-server/utils/config.ts +++ b/src-server/utils/config.ts @@ -4,6 +4,9 @@ export const DATABASE_URL = process.env.DATABASE_URL! export const OPENAI_BASE_URL = process.env.OPENAI_BASE_URL export const OPENAI_API_KEY = process.env.OPENAI_API_KEY export const S3_ENDPOINT = process.env.S3_ENDPOINT! +export const S3_PROTOCOL = process.env.S3_PROTOCOL || 'https' +export const S3_REGION = process.env.S3_REGION || 'us-east-1' +export const S3_TYPE = process.env.S3_TYPE || 'virtual-hosted' export const S3_BUCKET = process.env.S3_BUCKET! export const S3_ACCESS_KEY_ID = process.env.S3_ACCESS_KEY_ID! export const S3_SECRET_ACCESS_KEY = process.env.S3_SECRET_ACCESS_KEY! diff --git a/src-server/utils/s3.ts b/src-server/utils/s3.ts index edc99df..4af9725 100644 --- a/src-server/utils/s3.ts +++ b/src-server/utils/s3.ts @@ -1,13 +1,17 @@ import { AwsClient } from 'aws4fetch' -import { S3_ENDPOINT, S3_BUCKET, S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY } from './config' +import { S3_ENDPOINT, S3_PROTOCOL, S3_REGION, S3_TYPE, S3_BUCKET, S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY } from './config' const aws = new AwsClient({ accessKeyId: S3_ACCESS_KEY_ID, secretAccessKey: S3_SECRET_ACCESS_KEY, + service: 's3', + region: S3_REGION, }) function objectUrl(key: string) { - return `https://${S3_BUCKET}.${S3_ENDPOINT}/${key}` + return S3_TYPE === 'path' + ? `${S3_PROTOCOL}://${S3_ENDPOINT}/${S3_BUCKET}/${key}` + : `${S3_PROTOCOL}://${S3_BUCKET}.${S3_ENDPOINT}/${key}` } export async function presignedGetObject(key: string, { expires, contentDisposition }: {