diff --git a/serve.go b/serve.go index c1351eb..8fbd8d8 100644 --- a/serve.go +++ b/serve.go @@ -17,8 +17,10 @@ package main import ( + "context" "io" "net/http" + "strings" minio "github.com/minio/minio-go/v7" "golang.org/x/exp/slog" @@ -41,18 +43,8 @@ type handler struct { func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { domain := r.Host path := r.URL.Path - if path == "" || path == "/" { - path = "index.html" - } - object, err := h.minio.GetObject(r.Context(), domain, path, minio.GetObjectOptions{}) - if err != nil { - slog.Warn("error getting object from s3", "error", err, "domain", domain, "path", path) - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - stat, err := object.Stat() + object, stat, err := h.get(r.Context(), domain, path) if err != nil { resp := minio.ToErrorResponse(err) if resp.StatusCode == http.StatusNotFound { @@ -62,9 +54,8 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { slog.Info("served 404", "domain", domain, "path", path) return } - - slog.Warn("failed to stat object", "err", err, "bucket", domain, "path", path) - http.Error(w, err.Error(), http.StatusInternalServerError) + slog.Error("error getting object from storage", "bucket", domain, "object", path, "err", err) + http.Error(w, "internal server error", http.StatusInternalServerError) return } @@ -79,3 +70,29 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { slog.Info("served request", "domain", domain, "path", path, "size_bytes", n) } + +func (h handler) get(ctx context.Context, bucket string, path string) (*minio.Object, *minio.ObjectInfo, error) { + object, err := h.minio.GetObject(ctx, bucket, path, minio.GetObjectOptions{}) + if err != nil { + return nil, nil, err + } + + stat, err := object.Stat() + if err != nil { + resp := minio.ToErrorResponse(err) + if resp.StatusCode == http.StatusNotFound { + if strings.HasSuffix(path, "/index.html") { + return nil, nil, err + } + if !strings.HasSuffix(path, "/") { + path = path + "/" + } + path = path + "index.html" + return h.get(ctx, bucket, path) + } + + return nil, nil, err + } + + return object, &stat, nil +}