mirror of
https://github.com/go-gitea/gitea.git
synced 2025-12-11 08:44:40 +01:00
94 lines
2.5 KiB
Go
94 lines
2.5 KiB
Go
// Copyright 2025 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package renderplugin
|
|
|
|
import (
|
|
"net/http"
|
|
"os"
|
|
"path"
|
|
"strings"
|
|
|
|
"code.gitea.io/gitea/modules/json"
|
|
"code.gitea.io/gitea/modules/log"
|
|
"code.gitea.io/gitea/modules/renderplugin"
|
|
"code.gitea.io/gitea/modules/setting"
|
|
plugin_service "code.gitea.io/gitea/services/renderplugin"
|
|
)
|
|
|
|
// AssetsHandler returns an http.Handler that serves plugin metadata and static files.
|
|
func AssetsHandler() http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodGet && r.Method != http.MethodHead {
|
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
prefix := setting.AppSubURL + "/assets/render-plugins/"
|
|
if !strings.HasPrefix(r.URL.Path, prefix) {
|
|
w.WriteHeader(http.StatusNotFound)
|
|
return
|
|
}
|
|
rel := strings.TrimPrefix(r.URL.Path, prefix)
|
|
rel = strings.TrimLeft(rel, "/")
|
|
if rel == "" {
|
|
w.WriteHeader(http.StatusNotFound)
|
|
return
|
|
}
|
|
if rel == "index.json" {
|
|
serveMetadata(w, r)
|
|
return
|
|
}
|
|
parts := strings.SplitN(rel, "/", 2)
|
|
if len(parts) != 2 {
|
|
w.WriteHeader(http.StatusNotFound)
|
|
return
|
|
}
|
|
clean := path.Clean("/" + parts[1])
|
|
if clean == "/" {
|
|
w.WriteHeader(http.StatusNotFound)
|
|
return
|
|
}
|
|
clean = strings.TrimPrefix(clean, "/")
|
|
if strings.HasPrefix(clean, "../") {
|
|
w.WriteHeader(http.StatusNotFound)
|
|
return
|
|
}
|
|
objectPath := renderplugin.ObjectPath(parts[0], clean)
|
|
obj, err := renderplugin.Storage().Open(objectPath)
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
w.WriteHeader(http.StatusNotFound)
|
|
} else {
|
|
log.Error("Unable to open render plugin asset %s: %v", objectPath, err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
}
|
|
return
|
|
}
|
|
defer obj.Close()
|
|
info, err := obj.Stat()
|
|
if err != nil {
|
|
log.Error("Unable to stat render plugin asset %s: %v", objectPath, err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
http.ServeContent(w, r, path.Base(clean), info.ModTime(), obj)
|
|
})
|
|
}
|
|
|
|
func serveMetadata(w http.ResponseWriter, r *http.Request) {
|
|
meta, err := plugin_service.BuildMetadata(r.Context())
|
|
if err != nil {
|
|
log.Error("Unable to build render plugin metadata: %v", err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if r.Method == http.MethodHead {
|
|
w.WriteHeader(http.StatusOK)
|
|
return
|
|
}
|
|
if err := json.NewEncoder(w).Encode(meta); err != nil {
|
|
log.Error("Failed to encode render plugin metadata: %v", err)
|
|
}
|
|
}
|