mirror of
https://github.com/DullJZ/s3-balance.git
synced 2026-06-27 05:51:21 +08:00
70 lines
1.9 KiB
Go
70 lines
1.9 KiB
Go
package api
|
|
|
|
import (
|
|
"encoding/xml"
|
|
"fmt"
|
|
"net/http"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/DullJZ/s3-balance/internal/storage"
|
|
)
|
|
|
|
// sendXMLResponse 发送XML响应
|
|
func (h *S3Handler) sendXMLResponse(w http.ResponseWriter, statusCode int, data interface{}) {
|
|
w.Header().Set("Content-Type", "application/xml")
|
|
w.WriteHeader(statusCode)
|
|
|
|
encoder := xml.NewEncoder(w)
|
|
encoder.Indent("", " ")
|
|
|
|
// 写入XML声明
|
|
w.Write([]byte(xml.Header))
|
|
|
|
if err := encoder.Encode(data); err != nil {
|
|
// 如果编码失败,记录错误
|
|
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
|
}
|
|
}
|
|
|
|
// sendS3Error 发送S3错误响应
|
|
func (h *S3Handler) sendS3Error(w http.ResponseWriter, code string, message string, resource string) {
|
|
errorResp := ErrorResponse{
|
|
Code: code,
|
|
Message: message,
|
|
Resource: resource,
|
|
RequestID: fmt.Sprintf("%d", time.Now().UnixNano()),
|
|
}
|
|
|
|
w.Header().Set("X-Amz-Error-Code", code)
|
|
w.Header().Set("X-Amz-Error-Message", message)
|
|
|
|
statusCode := http.StatusBadRequest
|
|
switch code {
|
|
case "NoSuchBucket", "NoSuchKey":
|
|
statusCode = http.StatusNotFound
|
|
case "BucketAlreadyExists":
|
|
statusCode = http.StatusConflict
|
|
case "InvalidAccessKeyId", "SignatureDoesNotMatch", "AccessDenied":
|
|
statusCode = http.StatusForbidden
|
|
case "InternalError":
|
|
statusCode = http.StatusInternalServerError
|
|
case "InsufficientStorage":
|
|
statusCode = http.StatusInsufficientStorage
|
|
}
|
|
|
|
h.sendXMLResponse(w, statusCode, errorResp)
|
|
}
|
|
|
|
// setObjectHeaders 设置对象响应头
|
|
func (h *S3Handler) setObjectHeaders(w http.ResponseWriter, obj *storage.Object) {
|
|
w.Header().Set("Content-Length", strconv.FormatInt(obj.Size, 10))
|
|
w.Header().Set("Last-Modified", obj.UpdatedAt.Format(http.TimeFormat))
|
|
w.Header().Set("ETag", fmt.Sprintf("\"%x\"", obj.ID))
|
|
if obj.ContentType != "" {
|
|
w.Header().Set("Content-Type", obj.ContentType)
|
|
} else {
|
|
w.Header().Set("Content-Type", "application/octet-stream")
|
|
}
|
|
}
|