mirror of
https://github.com/DullJZ/s3-balance.git
synced 2026-07-03 17:11:20 +08:00
78 lines
1.4 KiB
Go
78 lines
1.4 KiB
Go
package middleware
|
|
|
|
import (
|
|
"net"
|
|
"net/http"
|
|
"strings"
|
|
)
|
|
|
|
// VirtualHostConfig controls host-style bucket resolution.
|
|
type VirtualHostConfig struct {
|
|
Enabled func() bool
|
|
BucketExists func(string) bool
|
|
}
|
|
|
|
// VirtualHost rewrites host-style requests (bucket.example.com) into path-style paths.
|
|
func VirtualHost(cfg VirtualHostConfig) func(http.Handler) http.Handler {
|
|
return func(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
enabled := false
|
|
if cfg.Enabled != nil {
|
|
enabled = cfg.Enabled()
|
|
}
|
|
if !enabled {
|
|
next.ServeHTTP(w, r)
|
|
return
|
|
}
|
|
|
|
bucket := bucketFromHost(r.Host)
|
|
if bucket == "" {
|
|
next.ServeHTTP(w, r)
|
|
return
|
|
}
|
|
|
|
if cfg.BucketExists != nil && !cfg.BucketExists(bucket) {
|
|
next.ServeHTTP(w, r)
|
|
return
|
|
}
|
|
|
|
if strings.HasPrefix(r.URL.Path, "/"+bucket) {
|
|
next.ServeHTTP(w, r)
|
|
return
|
|
}
|
|
|
|
newPath := "/" + bucket
|
|
if r.URL.Path != "/" {
|
|
newPath += r.URL.Path
|
|
}
|
|
|
|
clone := r.Clone(r.Context())
|
|
clone.URL.Path = newPath
|
|
clone.RequestURI = newPath
|
|
|
|
next.ServeHTTP(w, clone)
|
|
})
|
|
}
|
|
}
|
|
|
|
func bucketFromHost(host string) string {
|
|
if host == "" {
|
|
return ""
|
|
}
|
|
|
|
hostname := host
|
|
if strings.Contains(host, ":") {
|
|
h, _, err := net.SplitHostPort(host)
|
|
if err == nil {
|
|
hostname = h
|
|
}
|
|
}
|
|
|
|
parts := strings.Split(hostname, ".")
|
|
if len(parts) == 0 {
|
|
return ""
|
|
}
|
|
|
|
return parts[0]
|
|
}
|