Browse Source

api: return 500 instead of 404 in case of non-existing items (#2582)

This is needed to differentiate between calls to non-existent andpoints
and calls to valid endpoints, but with an ID pointing to a non-existing
item, and to return JSON in the latter case.
pull/2583/head
Alessandro Ros 2 years ago committed by GitHub
parent
commit
07ff79f553
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 112
      apidocs/openapi.yaml
  2. 49
      internal/core/api.go
  3. 10
      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/srt_server.go
  9. 4
      internal/core/webrtc_manager.go

112
apidocs/openapi.yaml

@ -634,7 +634,7 @@ paths: @@ -634,7 +634,7 @@ paths:
'400':
description: invalid request.
'500':
description: internal server error.
description: server error.
/v3/config/global/patch:
patch:
@ -653,7 +653,7 @@ paths: @@ -653,7 +653,7 @@ paths:
'400':
description: invalid request.
'500':
description: internal server error.
description: server error.
/v3/config/pathdefaults/get:
get:
@ -670,7 +670,7 @@ paths: @@ -670,7 +670,7 @@ paths:
'400':
description: invalid request.
'500':
description: internal server error.
description: server error.
/v3/config/pathdefaults/patch:
patch:
@ -689,7 +689,7 @@ paths: @@ -689,7 +689,7 @@ paths:
'400':
description: invalid request.
'500':
description: internal server error.
description: server error.
/v3/config/paths/list:
get:
@ -719,7 +719,7 @@ paths: @@ -719,7 +719,7 @@ paths:
'400':
description: invalid request.
'500':
description: internal server error.
description: server error.
/v3/config/paths/get/{name}:
get:
@ -743,7 +743,7 @@ paths: @@ -743,7 +743,7 @@ paths:
'400':
description: invalid request.
'500':
description: internal server error.
description: server error.
/v3/config/paths/add/{name}:
post:
@ -769,7 +769,7 @@ paths: @@ -769,7 +769,7 @@ paths:
'400':
description: invalid request.
'500':
description: internal server error.
description: server error.
/v3/config/paths/patch/{name}:
patch:
@ -794,10 +794,8 @@ paths: @@ -794,10 +794,8 @@ paths:
description: the request was successful.
'400':
description: invalid request.
'404':
description: configuration not found.
'500':
description: internal server error.
description: server error.
/v3/config/paths/replace/{name}:
post:
@ -822,10 +820,8 @@ paths: @@ -822,10 +820,8 @@ paths:
description: the request was successful.
'400':
description: invalid request.
'404':
description: configuration not found.
'500':
description: internal server error.
description: server error.
/v3/config/paths/delete/{name}:
delete:
@ -844,10 +840,8 @@ paths: @@ -844,10 +840,8 @@ paths:
description: the request was successful.
'400':
description: invalid request.
'404':
description: configuration not found.
'500':
description: internal server error.
description: server error.
/v3/hlsmuxers/list:
get:
@ -877,7 +871,7 @@ paths: @@ -877,7 +871,7 @@ paths:
'400':
description: invalid request.
'500':
description: internal server error.
description: server error.
/v3/hlsmuxers/get/{name}:
get:
@ -900,10 +894,8 @@ paths: @@ -900,10 +894,8 @@ paths:
$ref: '#/components/schemas/HLSMuxer'
'400':
description: invalid request.
'404':
description: muxer not found.
'500':
description: internal server error.
description: server error.
/v3/paths/list:
get:
@ -933,7 +925,7 @@ paths: @@ -933,7 +925,7 @@ paths:
'400':
description: invalid request.
'500':
description: internal server error.
description: server error.
/v3/paths/get/{name}:
get:
@ -956,10 +948,8 @@ paths: @@ -956,10 +948,8 @@ paths:
$ref: '#/components/schemas/Path'
'400':
description: invalid request.
'404':
description: path not found.
'500':
description: internal server error.
description: server error.
/v3/rtspconns/list:
get:
@ -989,7 +979,7 @@ paths: @@ -989,7 +979,7 @@ paths:
'400':
description: invalid request.
'500':
description: internal server error.
description: server error.
/v3/rtspconns/get/{id}:
get:
@ -1012,10 +1002,8 @@ paths: @@ -1012,10 +1002,8 @@ paths:
$ref: '#/components/schemas/RTSPConn'
'400':
description: invalid request.
'404':
description: connection not found.
'500':
description: internal server error.
description: server error.
/v3/rtspsessions/list:
get:
@ -1045,7 +1033,7 @@ paths: @@ -1045,7 +1033,7 @@ paths:
'400':
description: invalid request.
'500':
description: internal server error.
description: server error.
/v3/rtspsessions/get/{id}:
get:
@ -1068,10 +1056,8 @@ paths: @@ -1068,10 +1056,8 @@ paths:
$ref: '#/components/schemas/RTSPSession'
'400':
description: invalid request.
'404':
description: session not found.
'500':
description: internal server error.
description: server error.
/v3/rtspsessions/kick/{id}:
post:
@ -1090,10 +1076,8 @@ paths: @@ -1090,10 +1076,8 @@ paths:
description: the request was successful.
'400':
description: invalid request.
'404':
description: session not found.
'500':
description: internal server error.
description: server error.
/v3/rtspsconns/list:
get:
@ -1123,7 +1107,7 @@ paths: @@ -1123,7 +1107,7 @@ paths:
'400':
description: invalid request.
'500':
description: internal server error.
description: server error.
/v3/rtspsconns/get/{id}:
get:
@ -1146,10 +1130,8 @@ paths: @@ -1146,10 +1130,8 @@ paths:
$ref: '#/components/schemas/RTSPConn'
'400':
description: invalid request.
'404':
description: connection not found.
'500':
description: internal server error.
description: server error.
/v3/rtspssessions/list:
get:
@ -1178,10 +1160,8 @@ paths: @@ -1178,10 +1160,8 @@ paths:
$ref: '#/components/schemas/RTSPSessionList'
'400':
description: invalid request.
'404':
description: session not found.
'500':
description: internal server error.
description: server error.
/v3/rtspssessions/get/{id}:
get:
@ -1204,10 +1184,8 @@ paths: @@ -1204,10 +1184,8 @@ paths:
$ref: '#/components/schemas/RTSPSession'
'400':
description: invalid request.
'404':
description: session not found.
'500':
description: internal server error.
description: server error.
/v3/rtspssessions/kick/{id}:
post:
@ -1226,10 +1204,8 @@ paths: @@ -1226,10 +1204,8 @@ paths:
description: the request was successful.
'400':
description: invalid request.
'404':
description: session not found.
'500':
description: internal server error.
description: server error.
/v3/rtmpconns/list:
get:
@ -1259,7 +1235,7 @@ paths: @@ -1259,7 +1235,7 @@ paths:
'400':
description: invalid request.
'500':
description: internal server error.
description: server error.
/v3/rtmpconns/get/{id}:
get:
@ -1282,10 +1258,8 @@ paths: @@ -1282,10 +1258,8 @@ paths:
$ref: '#/components/schemas/RTMPConn'
'400':
description: invalid request.
'404':
description: connection not found.
'500':
description: internal server error.
description: server error.
/v3/rtmpconns/kick/{id}:
post:
@ -1304,10 +1278,8 @@ paths: @@ -1304,10 +1278,8 @@ paths:
description: the request was successful.
'400':
description: invalid request.
'404':
description: session not found.
'500':
description: internal server error.
description: server error.
/v3/rtmpsconns/list:
get:
@ -1337,7 +1309,7 @@ paths: @@ -1337,7 +1309,7 @@ paths:
'400':
description: invalid request.
'500':
description: internal server error.
description: server error.
/v3/rtmpsconns/get/{id}:
get:
@ -1360,10 +1332,8 @@ paths: @@ -1360,10 +1332,8 @@ paths:
$ref: '#/components/schemas/RTMPConn'
'400':
description: invalid request.
'404':
description: connection not found.
'500':
description: internal server error.
description: server error.
/v3/rtmpsconns/kick/{id}:
post:
@ -1382,10 +1352,8 @@ paths: @@ -1382,10 +1352,8 @@ paths:
description: the request was successful.
'400':
description: invalid request.
'404':
description: session not found.
'500':
description: internal server error.
description: server error.
/v3/srtconns/list:
get:
@ -1415,7 +1383,7 @@ paths: @@ -1415,7 +1383,7 @@ paths:
'400':
description: invalid request.
'500':
description: internal server error.
description: server error.
/v3/srtconns/get/{id}:
get:
@ -1438,10 +1406,8 @@ paths: @@ -1438,10 +1406,8 @@ paths:
$ref: '#/components/schemas/SRTConn'
'400':
description: invalid request.
'404':
description: connection not found.
'500':
description: internal server error.
description: server error.
/v3/srtconns/kick/{id}:
post:
@ -1460,10 +1426,8 @@ paths: @@ -1460,10 +1426,8 @@ paths:
description: the request was successful.
'400':
description: invalid request.
'404':
description: connection not found.
'500':
description: internal server error.
description: server error.
/v3/webrtcsessions/list:
get:
@ -1493,7 +1457,7 @@ paths: @@ -1493,7 +1457,7 @@ paths:
'400':
description: invalid request.
'500':
description: internal server error.
description: server error.
/v3/webrtcsessions/get/{id}:
get:
@ -1516,10 +1480,8 @@ paths: @@ -1516,10 +1480,8 @@ paths:
$ref: '#/components/schemas/WebRTCSession'
'400':
description: invalid request.
'404':
description: session not found.
'500':
description: internal server error.
description: server error.
/v3/webrtcsessions/kick/{id}:
post:
@ -1538,7 +1500,5 @@ paths: @@ -1538,7 +1500,5 @@ paths:
description: the request was successful.
'400':
description: invalid request.
'404':
description: session not found.
'500':
description: internal server error.
description: server error.

49
internal/core/api.go

@ -2,7 +2,6 @@ package core @@ -2,7 +2,6 @@ package core
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"reflect"
@ -19,8 +18,6 @@ import ( @@ -19,8 +18,6 @@ import (
"github.com/bluenviron/mediamtx/internal/protocols/httpserv"
)
var errAPINotFound = errors.New("not found")
func interfaceIsEmpty(i interface{}) bool {
return reflect.ValueOf(i).Kind() != reflect.Ptr || reflect.ValueOf(i).IsNil()
}
@ -290,18 +287,6 @@ func (a *api) writeServerError(ctx *gin.Context, err error) { @@ -290,18 +287,6 @@ func (a *api) writeServerError(ctx *gin.Context, err error) {
ctx.AbortWithStatus(http.StatusInternalServerError)
}
func (a *api) writeNotFound(ctx *gin.Context) {
ctx.AbortWithStatus(http.StatusNotFound)
}
func (a *api) writeServerErrorOrNotFound(ctx *gin.Context, err error) {
if err == errAPINotFound {
a.writeNotFound(ctx)
} else {
a.writeServerError(ctx, err)
}
}
func (a *api) onConfigGlobalGet(ctx *gin.Context) {
a.mutex.Lock()
c := a.conf
@ -412,7 +397,7 @@ func (a *api) onConfigPathsGet(ctx *gin.Context) { @@ -412,7 +397,7 @@ func (a *api) onConfigPathsGet(ctx *gin.Context) {
p, ok := c.OptionalPaths[name]
if !ok {
a.writeNotFound(ctx)
a.writeServerError(ctx, fmt.Errorf("path configuration not found"))
return
}
@ -587,7 +572,7 @@ func (a *api) onPathsGet(ctx *gin.Context) { @@ -587,7 +572,7 @@ func (a *api) onPathsGet(ctx *gin.Context) {
data, err := a.pathManager.apiPathsGet(name)
if err != nil {
a.writeServerErrorOrNotFound(ctx, err)
a.writeServerError(ctx, err)
return
}
@ -621,7 +606,7 @@ func (a *api) onRTSPConnsGet(ctx *gin.Context) { @@ -621,7 +606,7 @@ func (a *api) onRTSPConnsGet(ctx *gin.Context) {
data, err := a.rtspServer.apiConnsGet(uuid)
if err != nil {
a.writeServerErrorOrNotFound(ctx, err)
a.writeServerError(ctx, err)
return
}
@ -655,7 +640,7 @@ func (a *api) onRTSPSessionsGet(ctx *gin.Context) { @@ -655,7 +640,7 @@ func (a *api) onRTSPSessionsGet(ctx *gin.Context) {
data, err := a.rtspServer.apiSessionsGet(uuid)
if err != nil {
a.writeServerErrorOrNotFound(ctx, err)
a.writeServerError(ctx, err)
return
}
@ -671,7 +656,7 @@ func (a *api) onRTSPSessionsKick(ctx *gin.Context) { @@ -671,7 +656,7 @@ func (a *api) onRTSPSessionsKick(ctx *gin.Context) {
err = a.rtspServer.apiSessionsKick(uuid)
if err != nil {
a.writeServerErrorOrNotFound(ctx, err)
a.writeServerError(ctx, err)
return
}
@ -705,7 +690,7 @@ func (a *api) onRTSPSConnsGet(ctx *gin.Context) { @@ -705,7 +690,7 @@ func (a *api) onRTSPSConnsGet(ctx *gin.Context) {
data, err := a.rtspsServer.apiConnsGet(uuid)
if err != nil {
a.writeServerErrorOrNotFound(ctx, err)
a.writeServerError(ctx, err)
return
}
@ -739,7 +724,7 @@ func (a *api) onRTSPSSessionsGet(ctx *gin.Context) { @@ -739,7 +724,7 @@ func (a *api) onRTSPSSessionsGet(ctx *gin.Context) {
data, err := a.rtspsServer.apiSessionsGet(uuid)
if err != nil {
a.writeServerErrorOrNotFound(ctx, err)
a.writeServerError(ctx, err)
return
}
@ -755,7 +740,7 @@ func (a *api) onRTSPSSessionsKick(ctx *gin.Context) { @@ -755,7 +740,7 @@ func (a *api) onRTSPSSessionsKick(ctx *gin.Context) {
err = a.rtspsServer.apiSessionsKick(uuid)
if err != nil {
a.writeServerErrorOrNotFound(ctx, err)
a.writeServerError(ctx, err)
return
}
@ -789,7 +774,7 @@ func (a *api) onRTMPConnsGet(ctx *gin.Context) { @@ -789,7 +774,7 @@ func (a *api) onRTMPConnsGet(ctx *gin.Context) {
data, err := a.rtmpServer.apiConnsGet(uuid)
if err != nil {
a.writeServerErrorOrNotFound(ctx, err)
a.writeServerError(ctx, err)
return
}
@ -805,7 +790,7 @@ func (a *api) onRTMPConnsKick(ctx *gin.Context) { @@ -805,7 +790,7 @@ func (a *api) onRTMPConnsKick(ctx *gin.Context) {
err = a.rtmpServer.apiConnsKick(uuid)
if err != nil {
a.writeServerErrorOrNotFound(ctx, err)
a.writeServerError(ctx, err)
return
}
@ -839,7 +824,7 @@ func (a *api) onRTMPSConnsGet(ctx *gin.Context) { @@ -839,7 +824,7 @@ func (a *api) onRTMPSConnsGet(ctx *gin.Context) {
data, err := a.rtmpsServer.apiConnsGet(uuid)
if err != nil {
a.writeServerErrorOrNotFound(ctx, err)
a.writeServerError(ctx, err)
return
}
@ -855,7 +840,7 @@ func (a *api) onRTMPSConnsKick(ctx *gin.Context) { @@ -855,7 +840,7 @@ func (a *api) onRTMPSConnsKick(ctx *gin.Context) {
err = a.rtmpsServer.apiConnsKick(uuid)
if err != nil {
a.writeServerErrorOrNotFound(ctx, err)
a.writeServerError(ctx, err)
return
}
@ -889,7 +874,7 @@ func (a *api) onHLSMuxersGet(ctx *gin.Context) { @@ -889,7 +874,7 @@ func (a *api) onHLSMuxersGet(ctx *gin.Context) {
data, err := a.hlsManager.apiMuxersGet(name)
if err != nil {
a.writeServerErrorOrNotFound(ctx, err)
a.writeServerError(ctx, err)
return
}
@ -923,7 +908,7 @@ func (a *api) onWebRTCSessionsGet(ctx *gin.Context) { @@ -923,7 +908,7 @@ func (a *api) onWebRTCSessionsGet(ctx *gin.Context) {
data, err := a.webRTCManager.apiSessionsGet(uuid)
if err != nil {
a.writeServerErrorOrNotFound(ctx, err)
a.writeServerError(ctx, err)
return
}
@ -939,7 +924,7 @@ func (a *api) onWebRTCSessionsKick(ctx *gin.Context) { @@ -939,7 +924,7 @@ func (a *api) onWebRTCSessionsKick(ctx *gin.Context) {
err = a.webRTCManager.apiSessionsKick(uuid)
if err != nil {
a.writeServerErrorOrNotFound(ctx, err)
a.writeServerError(ctx, err)
return
}
@ -973,7 +958,7 @@ func (a *api) onSRTConnsGet(ctx *gin.Context) { @@ -973,7 +958,7 @@ func (a *api) onSRTConnsGet(ctx *gin.Context) {
data, err := a.srtServer.apiConnsGet(uuid)
if err != nil {
a.writeServerErrorOrNotFound(ctx, err)
a.writeServerError(ctx, err)
return
}
@ -989,7 +974,7 @@ func (a *api) onSRTConnsKick(ctx *gin.Context) { @@ -989,7 +974,7 @@ func (a *api) onSRTConnsKick(ctx *gin.Context) {
err = a.srtServer.apiConnsKick(uuid)
if err != nil {
a.writeServerErrorOrNotFound(ctx, err)
a.writeServerError(ctx, err)
return
}

10
internal/core/api_test.go

@ -398,7 +398,7 @@ func TestAPIConfigPathsDelete(t *testing.T) { @@ -398,7 +398,7 @@ func TestAPIConfigPathsDelete(t *testing.T) {
res, err := hc.Do(req)
require.NoError(t, err)
defer res.Body.Close()
require.Equal(t, http.StatusNotFound, res.StatusCode)
require.Equal(t, http.StatusInternalServerError, res.StatusCode)
}()
}
@ -650,7 +650,7 @@ func TestAPIPathsGet(t *testing.T) { @@ -650,7 +650,7 @@ func TestAPIPathsGet(t *testing.T) {
res, err := hc.Get("http://localhost:9997/v3/paths/get/" + pathName)
require.NoError(t, err)
defer res.Body.Close()
require.Equal(t, 404, res.StatusCode)
require.Equal(t, http.StatusInternalServerError, res.StatusCode)
}
})
}
@ -1331,7 +1331,7 @@ func TestAPIProtocolGetNotFound(t *testing.T) { @@ -1331,7 +1331,7 @@ func TestAPIProtocolGetNotFound(t *testing.T) {
res, err := hc.Do(req)
require.NoError(t, err)
defer res.Body.Close()
require.Equal(t, http.StatusNotFound, res.StatusCode)
require.Equal(t, http.StatusInternalServerError, res.StatusCode)
}()
})
}
@ -1537,13 +1537,13 @@ func TestAPIProtocolKickNotFound(t *testing.T) { @@ -1537,13 +1537,13 @@ func TestAPIProtocolKickNotFound(t *testing.T) {
}
func() {
req, err := http.NewRequest(http.MethodGet, "http://localhost:9997/v3/"+pa+"/kick/"+uuid.New().String(), nil)
req, err := http.NewRequest(http.MethodPost, "http://localhost:9997/v3/"+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)
require.Equal(t, http.StatusInternalServerError, res.StatusCode)
}()
})
}

2
internal/core/hls_manager.go

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

2
internal/core/path_manager.go

@ -383,7 +383,7 @@ func (pm *pathManager) doAPIPathsList(req pathAPIPathsListReq) { @@ -383,7 +383,7 @@ func (pm *pathManager) doAPIPathsList(req pathAPIPathsListReq) {
func (pm *pathManager) doAPIPathsGet(req pathAPIPathsGetReq) {
path, ok := pm.paths[req.name]
if !ok {
req.res <- pathAPIPathsGetRes{err: errAPINotFound}
req.res <- pathAPIPathsGetRes{err: fmt.Errorf("path not found")}
return
}

4
internal/core/rtmp_server.go

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

6
internal/core/rtsp_server.go

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

4
internal/core/srt_server.go

@ -208,7 +208,7 @@ outer: @@ -208,7 +208,7 @@ outer:
case req := <-s.chAPIConnsGet:
c := s.findConnByUUID(req.uuid)
if c == nil {
req.res <- srtServerAPIConnsGetRes{err: errAPINotFound}
req.res <- srtServerAPIConnsGetRes{err: fmt.Errorf("connection not found")}
continue
}
@ -217,7 +217,7 @@ outer: @@ -217,7 +217,7 @@ outer:
case req := <-s.chAPIConnsKick:
c := s.findConnByUUID(req.uuid)
if c == nil {
req.res <- srtServerAPIConnsKickRes{err: errAPINotFound}
req.res <- srtServerAPIConnsKickRes{err: fmt.Errorf("connection not found")}
continue
}

4
internal/core/webrtc_manager.go

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

Loading…
Cancel
Save