full proxy mode

This commit is contained in:
DullJZ
2025-09-22 23:52:50 +08:00
parent a1b5037174
commit 8ae5b8012a
5 changed files with 42 additions and 13 deletions
+1
View File
@@ -85,6 +85,7 @@ func main() {
cfg.S3API.AccessKey, cfg.S3API.AccessKey,
cfg.S3API.SecretKey, cfg.S3API.SecretKey,
metricsService, metricsService,
cfg.S3API.ProxyMode,
) )
// 设置路由 // 设置路由
+3 -3
View File
@@ -138,9 +138,9 @@ s3api:
virtual_host: false virtual_host: false
# 工作模式: # 工作模式:
# false (默认):预签名重定向模式,客户端直接与后端存储交互 # false:预签名重定向模式,客户端直接与后端存储交互
# true:代理模式,数据通过S3 Balance服务器传输 # true (默认):代理模式,数据通过S3 Balance服务器传输
proxy_mode: false proxy_mode: true
# 是否需要认证(开发环境可设为false) # 是否需要认证(开发环境可设为false)
auth_required: false auth_required: false
+33 -8
View File
@@ -82,9 +82,9 @@ func (h *S3Handler) handleGetObject(w http.ResponseWriter, r *http.Request, buck
return return
} }
// 默认使用预签名重定向模式,只有明确指定时才使用代理模式 // 根据配置决定使用代理模式还是重定向模式
if r.URL.Query().Get("proxy") == "true" { if h.proxyMode {
// 代理模式:服务器下载内容并返回给客户端 // 代理模式:流式传输内容给客户端
resp, err := http.Get(downloadInfo.URL) resp, err := http.Get(downloadInfo.URL)
if err != nil { if err != nil {
h.sendS3Error(w, "InternalError", "Failed to fetch object", key) h.sendS3Error(w, "InternalError", "Failed to fetch object", key)
@@ -92,13 +92,38 @@ func (h *S3Handler) handleGetObject(w http.ResponseWriter, r *http.Request, buck
} }
defer resp.Body.Close() defer resp.Body.Close()
// 复制响应头 // 检查响应状态
for k, v := range resp.Header { if resp.StatusCode != http.StatusOK {
w.Header()[k] = v w.WriteHeader(resp.StatusCode)
io.Copy(w, resp.Body)
return
} }
// 复制响应 // 复制重要的响应
io.Copy(w, resp.Body) if contentType := resp.Header.Get("Content-Type"); contentType != "" {
w.Header().Set("Content-Type", contentType)
}
if contentLength := resp.Header.Get("Content-Length"); contentLength != "" {
w.Header().Set("Content-Length", contentLength)
}
if lastModified := resp.Header.Get("Last-Modified"); lastModified != "" {
w.Header().Set("Last-Modified", lastModified)
}
if etag := resp.Header.Get("ETag"); etag != "" {
w.Header().Set("ETag", etag)
}
if contentEncoding := resp.Header.Get("Content-Encoding"); contentEncoding != "" {
w.Header().Set("Content-Encoding", contentEncoding)
}
if cacheControl := resp.Header.Get("Cache-Control"); cacheControl != "" {
w.Header().Set("Cache-Control", cacheControl)
}
// 流式复制响应体
_, err = io.Copy(w, resp.Body)
if err != nil {
log.Printf("Error streaming response body for key %s: %v", key, err)
}
} else { } else {
// 重定向模式:返回302重定向到预签名URL(默认) // 重定向模式:返回302重定向到预签名URL(默认)
http.Redirect(w, r, downloadInfo.URL, http.StatusFound) http.Redirect(w, r, downloadInfo.URL, http.StatusFound)
+3
View File
@@ -18,6 +18,7 @@ type S3Handler struct {
accessKey string accessKey string
secretKey string secretKey string
metrics *metrics.Metrics metrics *metrics.Metrics
proxyMode bool
} }
// NewS3Handler 创建新的S3兼容API处理器 // NewS3Handler 创建新的S3兼容API处理器
@@ -29,6 +30,7 @@ func NewS3Handler(
accessKey string, accessKey string,
secretKey string, secretKey string,
metrics *metrics.Metrics, metrics *metrics.Metrics,
proxyMode bool,
) *S3Handler { ) *S3Handler {
return &S3Handler{ return &S3Handler{
bucketManager: bucketManager, bucketManager: bucketManager,
@@ -38,6 +40,7 @@ func NewS3Handler(
accessKey: accessKey, accessKey: accessKey,
secretKey: secretKey, secretKey: secretKey,
metrics: metrics, metrics: metrics,
proxyMode: proxyMode,
} }
} }
+2 -2
View File
@@ -172,8 +172,8 @@ func (c *Config) SetDefaults() {
if c.S3API.SecretKey == "" { if c.S3API.SecretKey == "" {
c.S3API.SecretKey = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" c.S3API.SecretKey = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
} }
// 默认使用预签名模式(非代理模式) // 默认使用代理模式(避免302重定向
c.S3API.ProxyMode = false c.S3API.ProxyMode = true
c.S3API.AuthRequired = false c.S3API.AuthRequired = false
} }