package api import ( "errors" "fmt" "net/http" "github.com/bluenviron/mediamtx/internal/conf" "github.com/bluenviron/mediamtx/internal/conf/jsonwrapper" "github.com/bluenviron/mediamtx/internal/defs" "github.com/gin-gonic/gin" ) func (a *API) onConfigPathsList(ctx *gin.Context) { a.mutex.RLock() c := a.Conf a.mutex.RUnlock() data := &defs.APIPathConfList{ Items: make([]*conf.Path, len(c.Paths)), } for i, key := range sortedKeys(c.Paths) { data.Items[i] = c.Paths[key] } data.ItemCount = len(data.Items) pageCount, err := paginate(&data.Items, ctx.Query("itemsPerPage"), ctx.Query("page")) if err != nil { a.writeError(ctx, http.StatusBadRequest, err) return } data.PageCount = pageCount ctx.JSON(http.StatusOK, data) } func (a *API) onConfigPathsGet(ctx *gin.Context) { confName, ok := paramName(ctx) if !ok { a.writeError(ctx, http.StatusBadRequest, fmt.Errorf("invalid name")) return } a.mutex.RLock() c := a.Conf a.mutex.RUnlock() p, ok := c.Paths[confName] if !ok { a.writeError(ctx, http.StatusNotFound, fmt.Errorf("path configuration not found")) return } ctx.JSON(http.StatusOK, p) } func (a *API) onConfigPathsAdd(ctx *gin.Context) { //nolint:dupl confName, ok := paramName(ctx) if !ok { a.writeError(ctx, http.StatusBadRequest, fmt.Errorf("invalid name")) return } var p conf.OptionalPath err := jsonwrapper.Decode(ctx.Request.Body, &p) if err != nil { a.writeError(ctx, http.StatusBadRequest, err) return } a.mutex.Lock() defer a.mutex.Unlock() newConf := a.Conf.Clone() err = newConf.AddPath(confName, &p) if err != nil { a.writeError(ctx, http.StatusBadRequest, err) return } err = newConf.Validate(nil) if err != nil { a.writeError(ctx, http.StatusBadRequest, err) return } a.Conf = newConf a.Parent.APIConfigSet(newConf) ctx.Status(http.StatusOK) } func (a *API) onConfigPathsPatch(ctx *gin.Context) { //nolint:dupl confName, ok := paramName(ctx) if !ok { a.writeError(ctx, http.StatusBadRequest, fmt.Errorf("invalid name")) return } var p conf.OptionalPath err := jsonwrapper.Decode(ctx.Request.Body, &p) if err != nil { a.writeError(ctx, http.StatusBadRequest, err) return } a.mutex.Lock() defer a.mutex.Unlock() newConf := a.Conf.Clone() err = newConf.PatchPath(confName, &p) if err != nil { if errors.Is(err, conf.ErrPathNotFound) { a.writeError(ctx, http.StatusNotFound, err) } else { a.writeError(ctx, http.StatusBadRequest, err) } return } err = newConf.Validate(nil) if err != nil { a.writeError(ctx, http.StatusBadRequest, err) return } a.Conf = newConf a.Parent.APIConfigSet(newConf) ctx.Status(http.StatusOK) } func (a *API) onConfigPathsReplace(ctx *gin.Context) { //nolint:dupl confName, ok := paramName(ctx) if !ok { a.writeError(ctx, http.StatusBadRequest, fmt.Errorf("invalid name")) return } var p conf.OptionalPath err := jsonwrapper.Decode(ctx.Request.Body, &p) if err != nil { a.writeError(ctx, http.StatusBadRequest, err) return } a.mutex.Lock() defer a.mutex.Unlock() newConf := a.Conf.Clone() err = newConf.ReplacePath(confName, &p) if err != nil { if errors.Is(err, conf.ErrPathNotFound) { a.writeError(ctx, http.StatusNotFound, err) } else { a.writeError(ctx, http.StatusBadRequest, err) } return } err = newConf.Validate(nil) if err != nil { a.writeError(ctx, http.StatusBadRequest, err) return } a.Conf = newConf a.Parent.APIConfigSet(newConf) ctx.Status(http.StatusOK) } func (a *API) onConfigPathsDelete(ctx *gin.Context) { confName, ok := paramName(ctx) if !ok { a.writeError(ctx, http.StatusBadRequest, fmt.Errorf("invalid name")) return } a.mutex.Lock() defer a.mutex.Unlock() newConf := a.Conf.Clone() err := newConf.RemovePath(confName) if err != nil { if errors.Is(err, conf.ErrPathNotFound) { a.writeError(ctx, http.StatusNotFound, err) } else { a.writeError(ctx, http.StatusBadRequest, err) } return } err = newConf.Validate(nil) if err != nil { a.writeError(ctx, http.StatusBadRequest, err) return } a.Conf = newConf a.Parent.APIConfigSet(newConf) ctx.Status(http.StatusOK) }