feat: add independent platform modules and multi-provider storage

This commit is contained in:
2026-09-23 14:51:14 +08:00
parent f91034477b
commit 208a9c3fbd
57 changed files with 4890 additions and 48 deletions

View File

@@ -0,0 +1,63 @@
// Package storagefixture supplies a bounded protocol fixture, not a cloud service.
package storagefixture
import (
"crypto/md5"
"fmt"
"io"
"net/http"
"sync"
"time"
)
type value struct {
data []byte
contentType string
etag string
}
func Handler() http.Handler {
var mu sync.Mutex
values := map[string]value{}
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
mu.Lock()
defer mu.Unlock()
if r.Header.Get("Authorization") == "" && r.URL.Query().Get("X-Amz-Signature") == "" && r.URL.Query().Get("x-oss-signature") == "" {
http.Error(w, "signature required", 403)
return
}
key := r.URL.Path
switch r.Method {
case "PUT":
data, err := io.ReadAll(io.LimitReader(r.Body, 1025))
if err != nil || len(data) > 1024 {
http.Error(w, "too large", 413)
return
}
v := value{data: data, contentType: r.Header.Get("Content-Type"), etag: fmt.Sprintf("%x", md5.Sum(data))}
values[key] = v
w.Header().Set("ETag", `"`+v.etag+`"`)
w.WriteHeader(200)
case "DELETE":
delete(values, key)
w.WriteHeader(204)
case "GET", "HEAD":
v, ok := values[key]
if !ok {
w.Header().Set("Content-Type", "application/xml")
w.WriteHeader(404)
fmt.Fprint(w, `<Error><Code>NoSuchKey</Code><Message>not found</Message></Error>`)
return
}
w.Header().Set("Content-Length", fmt.Sprint(len(v.data)))
w.Header().Set("Content-Type", v.contentType)
w.Header().Set("ETag", `"`+v.etag+`"`)
w.Header().Set("Last-Modified", time.Now().UTC().Format(http.TimeFormat))
if r.Method == "GET" {
w.Write(v.data)
}
default:
http.Error(w, "unsupported", 405)
}
})
}