api: updated list/get/set file endpoint

This commit is contained in:
yusing 2025-01-07 10:57:53 +08:00
parent 0850562bf9
commit afefd925ea
4 changed files with 112 additions and 38 deletions

View file

@ -31,13 +31,12 @@ func NewHandler() http.Handler {
mux.HandleFunc("GET", "/v1/list", auth.RequireAuth(v1.List)) mux.HandleFunc("GET", "/v1/list", auth.RequireAuth(v1.List))
mux.HandleFunc("GET", "/v1/list/{what}", auth.RequireAuth(v1.List)) mux.HandleFunc("GET", "/v1/list/{what}", auth.RequireAuth(v1.List))
mux.HandleFunc("GET", "/v1/list/{what}/{which}", auth.RequireAuth(v1.List)) mux.HandleFunc("GET", "/v1/list/{what}/{which}", auth.RequireAuth(v1.List))
mux.HandleFunc("GET", "/v1/file", auth.RequireAuth(v1.GetFileContent)) mux.HandleFunc("GET", "/v1/file/{type}/{filename}", auth.RequireAuth(v1.GetFileContent))
mux.HandleFunc("GET", "/v1/file/{filename...}", auth.RequireAuth(v1.GetFileContent)) mux.HandleFunc("POST", "/v1/file/{type}/{filename}", auth.RequireAuth(v1.SetFileContent))
mux.HandleFunc("POST", "/v1/file/{filename...}", auth.RequireAuth(v1.SetFileContent)) mux.HandleFunc("PUT", "/v1/file/{type}/{filename}", auth.RequireAuth(v1.SetFileContent))
mux.HandleFunc("PUT", "/v1/file/{filename...}", auth.RequireAuth(v1.SetFileContent)) mux.HandleFunc("GET", "/v1/schema/{filename...}", v1.GetSchemaFile)
mux.HandleFunc("GET", "/v1/stats", v1.Stats) mux.HandleFunc("GET", "/v1/stats", v1.Stats)
mux.HandleFunc("GET", "/v1/stats/ws", v1.StatsWS) mux.HandleFunc("GET", "/v1/stats/ws", v1.StatsWS)
mux.HandleFunc("GET", "/v1/schema/{filename...}", v1.GetSchemaFile)
return mux return mux
} }

View file

@ -15,12 +15,59 @@ import (
"github.com/yusing/go-proxy/internal/route/provider" "github.com/yusing/go-proxy/internal/route/provider"
) )
func GetFileContent(w http.ResponseWriter, r *http.Request) { type FileType string
filename := r.PathValue("filename")
if filename == "" { const (
filename = common.ConfigFileName FileTypeConfig FileType = "config"
FileTypeProvider FileType = "provider"
FileTypeMiddleware FileType = "middleware"
)
func fileType(file string) FileType {
switch {
case strings.HasPrefix(path.Base(file), "config."):
return FileTypeConfig
case strings.HasPrefix(file, common.MiddlewareComposeBasePath):
return FileTypeMiddleware
} }
content, err := os.ReadFile(path.Join(common.ConfigBasePath, filename)) return FileTypeProvider
}
func (t FileType) IsValid() bool {
switch t {
case FileTypeConfig, FileTypeProvider, FileTypeMiddleware:
return true
}
return false
}
func (t FileType) GetPath(filename string) string {
if t == FileTypeMiddleware {
return path.Join(common.MiddlewareComposeBasePath, filename)
}
return path.Join(common.ConfigBasePath, filename)
}
func getArgs(r *http.Request) (fileType FileType, filename string, err error) {
fileType = FileType(r.PathValue("type"))
if !fileType.IsValid() {
err = U.ErrInvalidKey("type")
return
}
filename = r.PathValue("filename")
if filename == "" {
err = U.ErrMissingKey("filename")
}
return
}
func GetFileContent(w http.ResponseWriter, r *http.Request) {
fileType, filename, err := getArgs(r)
if err != nil {
U.RespondError(w, err, http.StatusBadRequest)
return
}
content, err := os.ReadFile(fileType.GetPath(filename))
if err != nil { if err != nil {
U.HandleErr(w, r, err) U.HandleErr(w, r, err)
return return
@ -29,9 +76,9 @@ func GetFileContent(w http.ResponseWriter, r *http.Request) {
} }
func SetFileContent(w http.ResponseWriter, r *http.Request) { func SetFileContent(w http.ResponseWriter, r *http.Request) {
filename := r.PathValue("filename") fileType, filename, err := getArgs(r)
if filename == "" { if err != nil {
U.HandleErr(w, r, U.ErrMissingKey("filename"), http.StatusBadRequest) U.RespondError(w, err, http.StatusBadRequest)
return return
} }
content, err := io.ReadAll(r.Body) content, err := io.ReadAll(r.Body)
@ -41,10 +88,10 @@ func SetFileContent(w http.ResponseWriter, r *http.Request) {
} }
var valErr E.Error var valErr E.Error
switch { switch fileType {
case filename == common.ConfigFileName: case FileTypeConfig:
valErr = config.Validate(content) valErr = config.Validate(content)
case strings.HasPrefix(filename, path.Base(common.MiddlewareComposeBasePath)): case FileTypeMiddleware:
errs := E.NewBuilder("middleware errors") errs := E.NewBuilder("middleware errors")
middleware.BuildMiddlewaresFromYAML(filename, content, errs) middleware.BuildMiddlewaresFromYAML(filename, content, errs)
valErr = errs.Error() valErr = errs.Error()
@ -57,23 +104,10 @@ func SetFileContent(w http.ResponseWriter, r *http.Request) {
return return
} }
err = os.WriteFile(path.Join(common.ConfigBasePath, filename), content, 0o644) err = os.WriteFile(fileType.GetPath(filename), content, 0o644)
if err != nil { if err != nil {
U.HandleErr(w, r, err) U.HandleErr(w, r, err)
return return
} }
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
} }
func GetSchemaFile(w http.ResponseWriter, r *http.Request) {
filename := r.PathValue("filename")
if filename == "" {
U.RespondError(w, U.ErrMissingKey("filename"), http.StatusBadRequest)
}
content, err := os.ReadFile(path.Join(common.SchemaBasePath, filename))
if err != nil {
U.HandleErr(w, r, err)
return
}
U.WriteBody(w, content)
}

View file

@ -16,7 +16,7 @@ import (
const ( const (
ListRoute = "route" ListRoute = "route"
ListRoutes = "routes" ListRoutes = "routes"
ListConfigFiles = "config_files" ListFiles = "files"
ListMiddlewares = "middlewares" ListMiddlewares = "middlewares"
ListMiddlewareTraces = "middleware_trace" ListMiddlewareTraces = "middleware_trace"
ListMatchDomains = "match_domains" ListMatchDomains = "match_domains"
@ -41,8 +41,8 @@ func List(w http.ResponseWriter, r *http.Request) {
} }
case ListRoutes: case ListRoutes:
U.RespondJSON(w, r, config.RoutesByAlias(route.RouteType(r.FormValue("type")))) U.RespondJSON(w, r, config.RoutesByAlias(route.RouteType(r.FormValue("type"))))
case ListConfigFiles: case ListFiles:
listConfigFiles(w, r) listFiles(w, r)
case ListMiddlewares: case ListMiddlewares:
U.RespondJSON(w, r, middleware.All()) U.RespondJSON(w, r, middleware.All())
case ListMiddlewareTraces: case ListMiddlewareTraces:
@ -70,14 +70,32 @@ func listRoute(which string) any {
return route return route
} }
func listConfigFiles(w http.ResponseWriter, r *http.Request) { func listFiles(w http.ResponseWriter, r *http.Request) {
files, err := utils.ListFiles(common.ConfigBasePath, 1) files, err := utils.ListFiles(common.ConfigBasePath, 0)
if err != nil { if err != nil {
U.HandleErr(w, r, err) U.HandleErr(w, r, err)
return return
} }
for i := range files { resp := map[FileType][]string{
files[i] = strings.TrimPrefix(files[i], common.ConfigBasePath+"/") FileTypeConfig: make([]string, 0),
FileTypeProvider: make([]string, 0),
FileTypeMiddleware: make([]string, 0),
} }
U.RespondJSON(w, r, files)
for _, file := range files {
t := fileType(file)
file = strings.TrimPrefix(file, common.ConfigBasePath+"/")
resp[t] = append(resp[t], file)
}
mids, err := utils.ListFiles(common.MiddlewareComposeBasePath, 0)
if err != nil {
U.HandleErr(w, r, err)
return
}
for _, mid := range mids {
mid = strings.TrimPrefix(mid, common.MiddlewareComposeBasePath+"/")
resp[FileTypeMiddleware] = append(resp[FileTypeMiddleware], mid)
}
U.RespondJSON(w, r, resp)
} }

23
internal/api/v1/schema.go Normal file
View file

@ -0,0 +1,23 @@
package v1
import (
"net/http"
"os"
"path"
U "github.com/yusing/go-proxy/internal/api/v1/utils"
"github.com/yusing/go-proxy/internal/common"
)
func GetSchemaFile(w http.ResponseWriter, r *http.Request) {
filename := r.PathValue("filename")
if filename == "" {
U.RespondError(w, U.ErrMissingKey("filename"), http.StatusBadRequest)
}
content, err := os.ReadFile(path.Join(common.SchemaBasePath, filename))
if err != nil {
U.HandleErr(w, r, err)
return
}
U.WriteBody(w, content)
}