diff --git a/internal/api/handler.go b/internal/api/handler.go index 7bdaa4b..0ea5aa3 100644 --- a/internal/api/handler.go +++ b/internal/api/handler.go @@ -31,13 +31,12 @@ func NewHandler() http.Handler { 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}/{which}", auth.RequireAuth(v1.List)) - mux.HandleFunc("GET", "/v1/file", auth.RequireAuth(v1.GetFileContent)) - mux.HandleFunc("GET", "/v1/file/{filename...}", auth.RequireAuth(v1.GetFileContent)) - mux.HandleFunc("POST", "/v1/file/{filename...}", auth.RequireAuth(v1.SetFileContent)) - mux.HandleFunc("PUT", "/v1/file/{filename...}", auth.RequireAuth(v1.SetFileContent)) + mux.HandleFunc("GET", "/v1/file/{type}/{filename}", auth.RequireAuth(v1.GetFileContent)) + mux.HandleFunc("POST", "/v1/file/{type}/{filename}", auth.RequireAuth(v1.SetFileContent)) + mux.HandleFunc("PUT", "/v1/file/{type}/{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/ws", v1.StatsWS) - mux.HandleFunc("GET", "/v1/schema/{filename...}", v1.GetSchemaFile) return mux } diff --git a/internal/api/v1/file.go b/internal/api/v1/file.go index c19518f..bc8720b 100644 --- a/internal/api/v1/file.go +++ b/internal/api/v1/file.go @@ -15,12 +15,59 @@ import ( "github.com/yusing/go-proxy/internal/route/provider" ) -func GetFileContent(w http.ResponseWriter, r *http.Request) { - filename := r.PathValue("filename") - if filename == "" { - filename = common.ConfigFileName +type FileType string + +const ( + 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 { U.HandleErr(w, r, err) return @@ -29,9 +76,9 @@ func GetFileContent(w http.ResponseWriter, r *http.Request) { } func SetFileContent(w http.ResponseWriter, r *http.Request) { - filename := r.PathValue("filename") - if filename == "" { - U.HandleErr(w, r, U.ErrMissingKey("filename"), http.StatusBadRequest) + fileType, filename, err := getArgs(r) + if err != nil { + U.RespondError(w, err, http.StatusBadRequest) return } content, err := io.ReadAll(r.Body) @@ -41,10 +88,10 @@ func SetFileContent(w http.ResponseWriter, r *http.Request) { } var valErr E.Error - switch { - case filename == common.ConfigFileName: + switch fileType { + case FileTypeConfig: valErr = config.Validate(content) - case strings.HasPrefix(filename, path.Base(common.MiddlewareComposeBasePath)): + case FileTypeMiddleware: errs := E.NewBuilder("middleware errors") middleware.BuildMiddlewaresFromYAML(filename, content, errs) valErr = errs.Error() @@ -57,23 +104,10 @@ func SetFileContent(w http.ResponseWriter, r *http.Request) { return } - err = os.WriteFile(path.Join(common.ConfigBasePath, filename), content, 0o644) + err = os.WriteFile(fileType.GetPath(filename), content, 0o644) if err != nil { U.HandleErr(w, r, err) return } 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) -} diff --git a/internal/api/v1/list.go b/internal/api/v1/list.go index 3e5665b..85d41a5 100644 --- a/internal/api/v1/list.go +++ b/internal/api/v1/list.go @@ -16,7 +16,7 @@ import ( const ( ListRoute = "route" ListRoutes = "routes" - ListConfigFiles = "config_files" + ListFiles = "files" ListMiddlewares = "middlewares" ListMiddlewareTraces = "middleware_trace" ListMatchDomains = "match_domains" @@ -41,8 +41,8 @@ func List(w http.ResponseWriter, r *http.Request) { } case ListRoutes: U.RespondJSON(w, r, config.RoutesByAlias(route.RouteType(r.FormValue("type")))) - case ListConfigFiles: - listConfigFiles(w, r) + case ListFiles: + listFiles(w, r) case ListMiddlewares: U.RespondJSON(w, r, middleware.All()) case ListMiddlewareTraces: @@ -70,14 +70,32 @@ func listRoute(which string) any { return route } -func listConfigFiles(w http.ResponseWriter, r *http.Request) { - files, err := utils.ListFiles(common.ConfigBasePath, 1) +func listFiles(w http.ResponseWriter, r *http.Request) { + files, err := utils.ListFiles(common.ConfigBasePath, 0) if err != nil { U.HandleErr(w, r, err) return } - for i := range files { - files[i] = strings.TrimPrefix(files[i], common.ConfigBasePath+"/") + resp := map[FileType][]string{ + 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) } diff --git a/internal/api/v1/schema.go b/internal/api/v1/schema.go new file mode 100644 index 0000000..86b732d --- /dev/null +++ b/internal/api/v1/schema.go @@ -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) +}