Browse Source

api: return 404 in /get and /kick endpoints (#1994) (#1995)

when an entity is not found
pull/1998/head
Alessandro Ros 2 years ago committed by GitHub
parent
commit
f1b975707a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 30
      apidocs/openapi.yaml
  2. 38
      internal/core/api.go
  3. 147
      internal/core/api_test.go
  4. 2
      internal/core/hls_manager.go
  5. 2
      internal/core/path_manager.go
  6. 4
      internal/core/rtmp_server.go
  7. 6
      internal/core/rtsp_server.go
  8. 4
      internal/core/webrtc_manager.go

30
apidocs/openapi.yaml

@ -666,6 +666,8 @@ paths: @@ -666,6 +666,8 @@ paths:
$ref: '#/components/schemas/HLSMuxer'
'400':
description: invalid request.
'404':
description: muxer not found.
'500':
description: internal server error.
@ -720,6 +722,8 @@ paths: @@ -720,6 +722,8 @@ paths:
$ref: '#/components/schemas/Path'
'400':
description: invalid request.
'404':
description: path not found.
'500':
description: internal server error.
@ -774,6 +778,8 @@ paths: @@ -774,6 +778,8 @@ paths:
$ref: '#/components/schemas/RTSPConn'
'400':
description: invalid request.
'404':
description: connection not found.
'500':
description: internal server error.
@ -828,6 +834,8 @@ paths: @@ -828,6 +834,8 @@ paths:
$ref: '#/components/schemas/RTSPSession'
'400':
description: invalid request.
'404':
description: session not found.
'500':
description: internal server error.
@ -848,6 +856,8 @@ paths: @@ -848,6 +856,8 @@ paths:
description: the request was successful.
'400':
description: invalid request.
'404':
description: session not found.
'500':
description: internal server error.
@ -902,6 +912,8 @@ paths: @@ -902,6 +912,8 @@ paths:
$ref: '#/components/schemas/RTSPConn'
'400':
description: invalid request.
'404':
description: connection not found.
'500':
description: internal server error.
@ -932,6 +944,8 @@ paths: @@ -932,6 +944,8 @@ paths:
$ref: '#/components/schemas/RTSPSessionsList'
'400':
description: invalid request.
'404':
description: session not found.
'500':
description: internal server error.
@ -956,6 +970,8 @@ paths: @@ -956,6 +970,8 @@ paths:
$ref: '#/components/schemas/RTSPSession'
'400':
description: invalid request.
'404':
description: session not found.
'500':
description: internal server error.
@ -976,6 +992,8 @@ paths: @@ -976,6 +992,8 @@ paths:
description: the request was successful.
'400':
description: invalid request.
'404':
description: session not found.
'500':
description: internal server error.
@ -1030,6 +1048,8 @@ paths: @@ -1030,6 +1048,8 @@ paths:
$ref: '#/components/schemas/RTMPConn'
'400':
description: invalid request.
'404':
description: connection not found.
'500':
description: internal server error.
@ -1050,6 +1070,8 @@ paths: @@ -1050,6 +1070,8 @@ paths:
description: the request was successful.
'400':
description: invalid request.
'404':
description: session not found.
'500':
description: internal server error.
@ -1104,6 +1126,8 @@ paths: @@ -1104,6 +1126,8 @@ paths:
$ref: '#/components/schemas/RTMPConn'
'400':
description: invalid request.
'404':
description: connection not found.
'500':
description: internal server error.
@ -1124,6 +1148,8 @@ paths: @@ -1124,6 +1148,8 @@ paths:
description: the request was successful.
'400':
description: invalid request.
'404':
description: session not found.
'500':
description: internal server error.
@ -1178,6 +1204,8 @@ paths: @@ -1178,6 +1204,8 @@ paths:
$ref: '#/components/schemas/WebRTCSession'
'400':
description: invalid request.
'404':
description: session not found.
'500':
description: internal server error.
@ -1198,5 +1226,7 @@ paths: @@ -1198,5 +1226,7 @@ paths:
description: the request was successful.
'400':
description: invalid request.
'404':
description: session not found.
'500':
description: internal server error.

38
internal/core/api.go

@ -2,6 +2,7 @@ package core @@ -2,6 +2,7 @@ package core
import (
"encoding/json"
"errors"
"net/http"
"reflect"
"strconv"
@ -14,6 +15,8 @@ import ( @@ -14,6 +15,8 @@ import (
"github.com/bluenviron/mediamtx/internal/logger"
)
var errAPINotFound = errors.New("not found")
func interfaceIsEmpty(i interface{}) bool {
return reflect.ValueOf(i).Kind() != reflect.Ptr || reflect.ValueOf(i).IsNil()
}
@ -128,6 +131,14 @@ func paginate(itemsPtr interface{}, itemsPerPageStr string, pageStr string) (int @@ -128,6 +131,14 @@ func paginate(itemsPtr interface{}, itemsPerPageStr string, pageStr string) (int
return paginate2(itemsPtr, itemsPerPage, page), nil
}
func abortWithError(ctx *gin.Context, err error) {
if err == errAPINotFound {
ctx.AbortWithStatus(http.StatusNotFound)
} else {
ctx.AbortWithStatus(http.StatusInternalServerError)
}
}
type apiPathManager interface {
apiPathsList() (*apiPathsList, error)
apiPathsGet(string) (*apiPath, error)
@ -422,13 +433,12 @@ func (a *api) onConfigPathsDelete(ctx *gin.Context) { @@ -422,13 +433,12 @@ func (a *api) onConfigPathsDelete(ctx *gin.Context) {
a.mutex.Lock()
defer a.mutex.Unlock()
newConf := a.conf.Clone()
if _, ok := newConf.Paths[name]; !ok {
ctx.AbortWithStatus(http.StatusBadRequest)
if _, ok := a.conf.Paths[name]; !ok {
ctx.AbortWithStatus(http.StatusNotFound)
return
}
newConf := a.conf.Clone()
delete(newConf.Paths, name)
err := newConf.Check()
@ -467,11 +477,7 @@ func (a *api) onPathsList(ctx *gin.Context) { @@ -467,11 +477,7 @@ func (a *api) onPathsList(ctx *gin.Context) {
func (a *api) onPathsGet(ctx *gin.Context) {
data, err := a.pathManager.apiPathsGet(ctx.Param("name"))
if err != nil {
if err.Error() == "not found" {
ctx.AbortWithStatus(http.StatusNotFound)
return
}
ctx.AbortWithStatus(http.StatusInternalServerError)
abortWithError(ctx, err)
return
}
@ -505,6 +511,7 @@ func (a *api) onRTSPConnsGet(ctx *gin.Context) { @@ -505,6 +511,7 @@ func (a *api) onRTSPConnsGet(ctx *gin.Context) {
data, err := a.rtspServer.apiConnsGet(uuid)
if err != nil {
abortWithError(ctx, err)
return
}
@ -538,6 +545,7 @@ func (a *api) onRTSPSessionsGet(ctx *gin.Context) { @@ -538,6 +545,7 @@ func (a *api) onRTSPSessionsGet(ctx *gin.Context) {
data, err := a.rtspServer.apiSessionsGet(uuid)
if err != nil {
abortWithError(ctx, err)
return
}
@ -553,6 +561,7 @@ func (a *api) onRTSPSessionsKick(ctx *gin.Context) { @@ -553,6 +561,7 @@ func (a *api) onRTSPSessionsKick(ctx *gin.Context) {
err = a.rtspServer.apiSessionsKick(uuid)
if err != nil {
abortWithError(ctx, err)
return
}
@ -586,6 +595,7 @@ func (a *api) onRTSPSConnsGet(ctx *gin.Context) { @@ -586,6 +595,7 @@ func (a *api) onRTSPSConnsGet(ctx *gin.Context) {
data, err := a.rtspsServer.apiConnsGet(uuid)
if err != nil {
abortWithError(ctx, err)
return
}
@ -619,6 +629,7 @@ func (a *api) onRTSPSSessionsGet(ctx *gin.Context) { @@ -619,6 +629,7 @@ func (a *api) onRTSPSSessionsGet(ctx *gin.Context) {
data, err := a.rtspsServer.apiSessionsGet(uuid)
if err != nil {
abortWithError(ctx, err)
return
}
@ -634,6 +645,7 @@ func (a *api) onRTSPSSessionsKick(ctx *gin.Context) { @@ -634,6 +645,7 @@ func (a *api) onRTSPSSessionsKick(ctx *gin.Context) {
err = a.rtspsServer.apiSessionsKick(uuid)
if err != nil {
abortWithError(ctx, err)
return
}
@ -667,6 +679,7 @@ func (a *api) onRTMPConnsGet(ctx *gin.Context) { @@ -667,6 +679,7 @@ func (a *api) onRTMPConnsGet(ctx *gin.Context) {
data, err := a.rtmpServer.apiConnsGet(uuid)
if err != nil {
abortWithError(ctx, err)
return
}
@ -682,6 +695,7 @@ func (a *api) onRTMPConnsKick(ctx *gin.Context) { @@ -682,6 +695,7 @@ func (a *api) onRTMPConnsKick(ctx *gin.Context) {
err = a.rtmpServer.apiConnsKick(uuid)
if err != nil {
abortWithError(ctx, err)
return
}
@ -715,6 +729,7 @@ func (a *api) onRTMPSConnsGet(ctx *gin.Context) { @@ -715,6 +729,7 @@ func (a *api) onRTMPSConnsGet(ctx *gin.Context) {
data, err := a.rtmpsServer.apiConnsGet(uuid)
if err != nil {
abortWithError(ctx, err)
return
}
@ -730,6 +745,7 @@ func (a *api) onRTMPSConnsKick(ctx *gin.Context) { @@ -730,6 +745,7 @@ func (a *api) onRTMPSConnsKick(ctx *gin.Context) {
err = a.rtmpsServer.apiConnsKick(uuid)
if err != nil {
abortWithError(ctx, err)
return
}
@ -757,7 +773,7 @@ func (a *api) onHLSMuxersList(ctx *gin.Context) { @@ -757,7 +773,7 @@ func (a *api) onHLSMuxersList(ctx *gin.Context) {
func (a *api) onHLSMuxersGet(ctx *gin.Context) {
data, err := a.hlsManager.apiMuxersGet(ctx.Param("name"))
if err != nil {
ctx.AbortWithStatus(http.StatusInternalServerError)
abortWithError(ctx, err)
return
}
@ -791,6 +807,7 @@ func (a *api) onWebRTCSessionsGet(ctx *gin.Context) { @@ -791,6 +807,7 @@ func (a *api) onWebRTCSessionsGet(ctx *gin.Context) {
data, err := a.webRTCManager.apiSessionsGet(uuid)
if err != nil {
abortWithError(ctx, err)
return
}
@ -806,6 +823,7 @@ func (a *api) onWebRTCSessionsKick(ctx *gin.Context) { @@ -806,6 +823,7 @@ func (a *api) onWebRTCSessionsKick(ctx *gin.Context) {
err = a.webRTCManager.apiSessionsKick(uuid)
if err != nil {
abortWithError(ctx, err)
return
}

147
internal/core/api_test.go

@ -17,6 +17,7 @@ import ( @@ -17,6 +17,7 @@ import (
"github.com/bluenviron/gortsplib/v3/pkg/formats"
"github.com/bluenviron/gortsplib/v3/pkg/media"
"github.com/bluenviron/mediacommon/pkg/codecs/mpeg4audio"
"github.com/google/uuid"
"github.com/pion/rtp"
"github.com/stretchr/testify/require"
@ -991,6 +992,90 @@ func TestAPIProtocolGet(t *testing.T) { @@ -991,6 +992,90 @@ func TestAPIProtocolGet(t *testing.T) {
}
}
func TestAPIProtocolGetNotFound(t *testing.T) {
serverCertFpath, err := writeTempFile(serverCert)
require.NoError(t, err)
defer os.Remove(serverCertFpath)
serverKeyFpath, err := writeTempFile(serverKey)
require.NoError(t, err)
defer os.Remove(serverKeyFpath)
for _, ca := range []string{
"rtsp conns",
"rtsp sessions",
"rtsps conns",
"rtsps sessions",
"rtmp",
"rtmps",
"hls",
"webrtc",
} {
t.Run(ca, func(t *testing.T) {
conf := "api: yes\n"
switch ca {
case "rtsps conns", "rtsps sessions":
conf += "protocols: [tcp]\n" +
"encryption: strict\n" +
"serverCert: " + serverCertFpath + "\n" +
"serverKey: " + serverKeyFpath + "\n"
case "rtmps":
conf += "rtmpEncryption: strict\n" +
"rtmpServerCert: " + serverCertFpath + "\n" +
"rtmpServerKey: " + serverKeyFpath + "\n"
}
conf += "paths:\n" +
" all:\n"
p, ok := newInstance(conf)
require.Equal(t, true, ok)
defer p.Close()
hc := &http.Client{Transport: &http.Transport{}}
var pa string
switch ca {
case "rtsp conns":
pa = "rtspconns"
case "rtsp sessions":
pa = "rtspsessions"
case "rtsps conns":
pa = "rtspsconns"
case "rtsps sessions":
pa = "rtspssessions"
case "rtmp":
pa = "rtmpconns"
case "rtmps":
pa = "rtmpsconns"
case "hls":
pa = "hlsmuxers"
case "webrtc":
pa = "webrtcsessions"
}
func() {
req, err := http.NewRequest("GET", "http://localhost:9997/v2/"+pa+"/get/"+uuid.New().String(), nil)
require.NoError(t, err)
res, err := hc.Do(req)
require.NoError(t, err)
defer res.Body.Close()
require.Equal(t, http.StatusNotFound, res.StatusCode)
}()
})
}
}
func TestAPIProtocolKick(t *testing.T) {
serverCertFpath, err := writeTempFile(serverCert)
require.NoError(t, err)
@ -1100,3 +1185,65 @@ func TestAPIProtocolKick(t *testing.T) { @@ -1100,3 +1185,65 @@ func TestAPIProtocolKick(t *testing.T) {
})
}
}
func TestAPIProtocolKickNotFound(t *testing.T) {
serverCertFpath, err := writeTempFile(serverCert)
require.NoError(t, err)
defer os.Remove(serverCertFpath)
serverKeyFpath, err := writeTempFile(serverKey)
require.NoError(t, err)
defer os.Remove(serverKeyFpath)
for _, ca := range []string{
"rtsp",
"rtsps",
"rtmp",
"webrtc",
} {
t.Run(ca, func(t *testing.T) {
conf := "api: yes\n"
if ca == "rtsps" {
conf += "protocols: [tcp]\n" +
"encryption: strict\n" +
"serverCert: " + serverCertFpath + "\n" +
"serverKey: " + serverKeyFpath + "\n"
}
conf += "paths:\n" +
" all:\n"
p, ok := newInstance(conf)
require.Equal(t, true, ok)
defer p.Close()
hc := &http.Client{Transport: &http.Transport{}}
var pa string
switch ca {
case "rtsp":
pa = "rtspsessions"
case "rtsps":
pa = "rtspssessions"
case "rtmp":
pa = "rtmpconns"
case "webrtc":
pa = "webrtcsessions"
}
func() {
req, err := http.NewRequest("GET", "http://localhost:9997/v2/"+pa+"/kick/"+uuid.New().String(), nil)
require.NoError(t, err)
res, err := hc.Do(req)
require.NoError(t, err)
defer res.Body.Close()
require.Equal(t, http.StatusNotFound, res.StatusCode)
}()
})
}
}

2
internal/core/hls_manager.go

@ -209,7 +209,7 @@ outer: @@ -209,7 +209,7 @@ outer:
case req := <-m.chAPIMuxerGet:
muxer, ok := m.muxers[req.name]
if !ok {
req.res <- hlsManagerAPIMuxersGetRes{err: fmt.Errorf("not found")}
req.res <- hlsManagerAPIMuxersGetRes{err: errAPINotFound}
continue
}

2
internal/core/path_manager.go

@ -300,7 +300,7 @@ outer: @@ -300,7 +300,7 @@ outer:
case req := <-pm.chAPIPathsGet:
path, ok := pm.paths[req.name]
if !ok {
req.res <- pathAPIPathsGetRes{err: fmt.Errorf("not found")}
req.res <- pathAPIPathsGetRes{err: errAPINotFound}
continue
}

4
internal/core/rtmp_server.go

@ -233,7 +233,7 @@ outer: @@ -233,7 +233,7 @@ outer:
case req := <-s.chAPIConnsGet:
c := s.findConnByUUID(req.uuid)
if c == nil {
req.res <- rtmpServerAPIConnsGetRes{err: fmt.Errorf("not found")}
req.res <- rtmpServerAPIConnsGetRes{err: errAPINotFound}
continue
}
@ -242,7 +242,7 @@ outer: @@ -242,7 +242,7 @@ outer:
case req := <-s.chAPIConnsKick:
c := s.findConnByUUID(req.uuid)
if c == nil {
req.res <- rtmpServerAPIConnsKickRes{fmt.Errorf("not found")}
req.res <- rtmpServerAPIConnsKickRes{err: errAPINotFound}
continue
}

6
internal/core/rtsp_server.go

@ -381,7 +381,7 @@ func (s *rtspServer) apiConnsGet(uuid uuid.UUID) (*apiRTSPConn, error) { @@ -381,7 +381,7 @@ func (s *rtspServer) apiConnsGet(uuid uuid.UUID) (*apiRTSPConn, error) {
conn := s.findConnByUUID(uuid)
if conn == nil {
return nil, fmt.Errorf("not found")
return nil, errAPINotFound
}
return conn.apiItem(), nil
@ -426,7 +426,7 @@ func (s *rtspServer) apiSessionsGet(uuid uuid.UUID) (*apiRTSPSession, error) { @@ -426,7 +426,7 @@ func (s *rtspServer) apiSessionsGet(uuid uuid.UUID) (*apiRTSPSession, error) {
_, sx := s.findSessionByUUID(uuid)
if sx == nil {
return nil, fmt.Errorf("not found")
return nil, errAPINotFound
}
return sx.apiItem(), nil
@ -445,7 +445,7 @@ func (s *rtspServer) apiSessionsKick(uuid uuid.UUID) error { @@ -445,7 +445,7 @@ func (s *rtspServer) apiSessionsKick(uuid uuid.UUID) error {
key, sx := s.findSessionByUUID(uuid)
if sx == nil {
return fmt.Errorf("not found")
return errAPINotFound
}
sx.close()

4
internal/core/webrtc_manager.go

@ -348,7 +348,7 @@ outer: @@ -348,7 +348,7 @@ outer:
case req := <-m.chAPISessionsGet:
sx := m.findSessionByUUID(req.uuid)
if sx == nil {
req.res <- webRTCManagerAPISessionsGetRes{err: fmt.Errorf("not found")}
req.res <- webRTCManagerAPISessionsGetRes{err: errAPINotFound}
continue
}
@ -357,7 +357,7 @@ outer: @@ -357,7 +357,7 @@ outer:
case req := <-m.chAPIConnsKick:
sx := m.findSessionByUUID(req.uuid)
if sx == nil {
req.res <- webRTCManagerAPISessionsKickRes{fmt.Errorf("not found")}
req.res <- webRTCManagerAPISessionsKickRes{err: errAPINotFound}
continue
}

Loading…
Cancel
Save