mirror of
https://github.com/aler9/gortsplib
synced 2025-10-04 14:52:46 +08:00
server: fill ctx.Query correctly (#73)
This commit is contained in:
15
pkg/base/path.go
Normal file
15
pkg/base/path.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// PathSplitQuery splits a path from a query.
|
||||
func PathSplitQuery(pathAndQuery string) (string, string) {
|
||||
i := strings.Index(pathAndQuery, "?")
|
||||
if i >= 0 {
|
||||
return pathAndQuery[:i], pathAndQuery[i+1:]
|
||||
}
|
||||
|
||||
return pathAndQuery, ""
|
||||
}
|
30
pkg/base/path_test.go
Normal file
30
pkg/base/path_test.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestPathSplitQuery(t *testing.T) {
|
||||
for _, ca := range []struct {
|
||||
a string
|
||||
b string
|
||||
c string
|
||||
}{
|
||||
{
|
||||
"test?a=b",
|
||||
"test",
|
||||
"a=b",
|
||||
},
|
||||
{
|
||||
"test",
|
||||
"test",
|
||||
"",
|
||||
},
|
||||
} {
|
||||
b, c := PathSplitQuery(ca.a)
|
||||
require.Equal(t, ca.b, b)
|
||||
require.Equal(t, ca.c, c)
|
||||
}
|
||||
}
|
@@ -3,19 +3,8 @@ package base
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// PathSplitQuery splits a path from a query.
|
||||
func PathSplitQuery(pathAndQuery string) (string, string) {
|
||||
i := strings.Index(pathAndQuery, "?")
|
||||
if i >= 0 {
|
||||
return pathAndQuery[:i], pathAndQuery[i:]
|
||||
}
|
||||
|
||||
return pathAndQuery, ""
|
||||
}
|
||||
|
||||
// URL is a RTSP URL.
|
||||
// This is basically an HTTP URL with some additional functions to handle
|
||||
// control attributes.
|
||||
@@ -73,17 +62,6 @@ func (u *URL) CloneWithoutCredentials() *URL {
|
||||
})
|
||||
}
|
||||
|
||||
// RTSPPath returns the path of a RTSP URL.
|
||||
func (u *URL) RTSPPath() (string, bool) {
|
||||
pathAndQuery, ok := u.RTSPPathAndQuery()
|
||||
if !ok {
|
||||
return "", false
|
||||
}
|
||||
|
||||
path, _ := PathSplitQuery(pathAndQuery)
|
||||
return path, true
|
||||
}
|
||||
|
||||
// RTSPPathAndQuery returns the path and query of a RTSP URL.
|
||||
func (u *URL) RTSPPathAndQuery() (string, bool) {
|
||||
var pathAndQuery string
|
||||
|
@@ -14,7 +14,7 @@ func mustParseURL(s string) *URL {
|
||||
return u
|
||||
}
|
||||
|
||||
func TestURLErrors(t *testing.T) {
|
||||
func TestURLParseErrors(t *testing.T) {
|
||||
for _, ca := range []struct {
|
||||
name string
|
||||
enc string
|
||||
@@ -48,42 +48,6 @@ func TestURLErrors(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestURLRTSPPath(t *testing.T) {
|
||||
for _, ca := range []struct {
|
||||
u *URL
|
||||
b string
|
||||
}{
|
||||
{
|
||||
mustParseURL("rtsp://localhost:8554/teststream"),
|
||||
"teststream",
|
||||
},
|
||||
{
|
||||
mustParseURL("rtsp://localhost:8554/test/stream"),
|
||||
"test/stream",
|
||||
},
|
||||
{
|
||||
mustParseURL("rtsp://192.168.1.99:554/test?user=tmp&password=BagRep1&channel=1&stream=0.sdp"),
|
||||
"test",
|
||||
},
|
||||
{
|
||||
mustParseURL("rtsp://192.168.1.99:554/te!st?user=tmp&password=BagRep1!&channel=1&stream=0.sdp"),
|
||||
"te!st",
|
||||
},
|
||||
{
|
||||
mustParseURL("rtsp://192.168.1.99:554/user=tmp&password=BagRep1!&channel=1&stream=0.sdp"),
|
||||
"user=tmp&password=BagRep1!&channel=1&stream=0.sdp",
|
||||
},
|
||||
{
|
||||
mustParseURL("rtsp://localhost:8554/teststream?query1?query2"),
|
||||
"teststream",
|
||||
},
|
||||
} {
|
||||
b, ok := ca.u.RTSPPath()
|
||||
require.Equal(t, true, ok)
|
||||
require.Equal(t, ca.b, b)
|
||||
}
|
||||
}
|
||||
|
||||
func TestURLClone(t *testing.T) {
|
||||
u := mustParseURL("rtsp://localhost:8554/test/stream")
|
||||
u2 := u.Clone()
|
||||
@@ -102,12 +66,6 @@ func TestURLClone(t *testing.T) {
|
||||
}, u2)
|
||||
}
|
||||
|
||||
func TestURLErrorRTSPPath(t *testing.T) {
|
||||
u := mustParseURL("rtsp://localhost:8554")
|
||||
_, ok := u.RTSPPath()
|
||||
require.Equal(t, false, ok)
|
||||
}
|
||||
|
||||
func TestURLRTSPPathAndQuery(t *testing.T) {
|
||||
for _, ca := range []struct {
|
||||
u *URL
|
||||
|
@@ -286,11 +286,16 @@ func TestServerHighLevelPublishRead(t *testing.T) {
|
||||
}
|
||||
},
|
||||
onDescribe: func(ctx *ServerHandlerOnDescribeCtx) (*base.Response, *ServerStream, error) {
|
||||
if ctx.Path != "teststream" {
|
||||
if ctx.Path != "test/stream" {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusBadRequest,
|
||||
}, nil, fmt.Errorf("invalid path (%s)", ctx.Req.URL)
|
||||
}
|
||||
if ctx.Query != "key=val" {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusBadRequest,
|
||||
}, nil, fmt.Errorf("invalid query (%s)", ctx.Query)
|
||||
}
|
||||
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
@@ -306,11 +311,16 @@ func TestServerHighLevelPublishRead(t *testing.T) {
|
||||
}, stream, nil
|
||||
},
|
||||
onAnnounce: func(ctx *ServerHandlerOnAnnounceCtx) (*base.Response, error) {
|
||||
if ctx.Path != "teststream" {
|
||||
if ctx.Path != "test/stream" {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusBadRequest,
|
||||
}, fmt.Errorf("invalid path (%s)", ctx.Req.URL)
|
||||
}
|
||||
if ctx.Query != "key=val" {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusBadRequest,
|
||||
}, fmt.Errorf("invalid query (%s)", ctx.Query)
|
||||
}
|
||||
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
@@ -329,11 +339,16 @@ func TestServerHighLevelPublishRead(t *testing.T) {
|
||||
}, nil
|
||||
},
|
||||
onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *ServerStream, error) {
|
||||
if ctx.Path != "teststream" {
|
||||
if ctx.Path != "test/stream" {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusBadRequest,
|
||||
}, nil, fmt.Errorf("invalid path (%s)", ctx.Req.URL)
|
||||
}
|
||||
if ctx.Query != "key=val" {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusBadRequest,
|
||||
}, nil, fmt.Errorf("invalid query (%s)", ctx.Query)
|
||||
}
|
||||
|
||||
if stream == nil {
|
||||
return &base.Response{
|
||||
@@ -346,22 +361,32 @@ func TestServerHighLevelPublishRead(t *testing.T) {
|
||||
}, stream, nil
|
||||
},
|
||||
onPlay: func(ctx *ServerHandlerOnPlayCtx) (*base.Response, error) {
|
||||
if ctx.Path != "teststream" {
|
||||
if ctx.Path != "test/stream" {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusBadRequest,
|
||||
}, fmt.Errorf("invalid path (%s)", ctx.Req.URL)
|
||||
}
|
||||
if ctx.Query != "key=val" {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusBadRequest,
|
||||
}, fmt.Errorf("invalid query (%s)", ctx.Query)
|
||||
}
|
||||
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
}, nil
|
||||
},
|
||||
onRecord: func(ctx *ServerHandlerOnRecordCtx) (*base.Response, error) {
|
||||
if ctx.Path != "teststream" {
|
||||
if ctx.Path != "test/stream" {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusBadRequest,
|
||||
}, fmt.Errorf("invalid path (%s)", ctx.Req.URL)
|
||||
}
|
||||
if ctx.Query != "key=val" {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusBadRequest,
|
||||
}, fmt.Errorf("invalid query (%s)", ctx.Query)
|
||||
}
|
||||
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
@@ -415,7 +440,7 @@ func TestServerHighLevelPublishRead(t *testing.T) {
|
||||
"-c", "copy",
|
||||
"-f", "rtsp",
|
||||
"-rtsp_transport", ts,
|
||||
proto + "://localhost:8554/teststream",
|
||||
proto + "://localhost:8554/test/stream?key=val",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
defer cnt1.close()
|
||||
@@ -431,7 +456,7 @@ func TestServerHighLevelPublishRead(t *testing.T) {
|
||||
|
||||
cnt1, err := newContainer("gstreamer", "publish", []string{
|
||||
"filesrc location=emptyvideo.mkv ! matroskademux ! video/x-h264 ! rtspclientsink " +
|
||||
"location=" + proto + "://127.0.0.1:8554/teststream protocols=" + ts +
|
||||
"location=" + proto + "://127.0.0.1:8554/test/stream?key=val protocols=" + ts +
|
||||
" tls-validation-flags=0 latency=0 timeout=0 rtx-time=0",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@@ -456,7 +481,7 @@ func TestServerHighLevelPublishRead(t *testing.T) {
|
||||
|
||||
cnt2, err := newContainer("ffmpeg", "read", []string{
|
||||
"-rtsp_transport", ts,
|
||||
"-i", proto + "://localhost:8554/teststream",
|
||||
"-i", proto + "://localhost:8554/test/stream?key=val",
|
||||
"-vframes", "1",
|
||||
"-f", "image2",
|
||||
"-y", "/dev/null",
|
||||
@@ -477,7 +502,7 @@ func TestServerHighLevelPublishRead(t *testing.T) {
|
||||
}()
|
||||
|
||||
cnt2, err := newContainer("gstreamer", "read", []string{
|
||||
"rtspsrc location=" + proto + "://127.0.0.1:8554/teststream protocols=" + ts +
|
||||
"rtspsrc location=" + proto + "://127.0.0.1:8554/test/stream?key=val protocols=" + ts +
|
||||
" tls-validation-flags=0 latency=0 " +
|
||||
"! application/x-rtp,media=video ! decodebin ! exitafterframe ! fakesink",
|
||||
})
|
||||
|
@@ -334,7 +334,7 @@ func (sc *ServerConn) handleRequest(req *base.Request) (*base.Response, error) {
|
||||
|
||||
case base.Describe:
|
||||
if h, ok := sc.s.Handler.(ServerHandlerOnDescribe); ok {
|
||||
pathAndQuery, ok := req.URL.RTSPPath()
|
||||
pathAndQuery, ok := req.URL.RTSPPathAndQuery()
|
||||
if !ok {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusBadRequest,
|
||||
@@ -431,7 +431,7 @@ func (sc *ServerConn) handleRequest(req *base.Request) (*base.Response, error) {
|
||||
|
||||
// handle request here
|
||||
if h, ok := sc.s.Handler.(ServerHandlerOnGetParameter); ok {
|
||||
pathAndQuery, ok := req.URL.RTSPPath()
|
||||
pathAndQuery, ok := req.URL.RTSPPathAndQuery()
|
||||
if !ok {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusBadRequest,
|
||||
@@ -450,7 +450,7 @@ func (sc *ServerConn) handleRequest(req *base.Request) (*base.Response, error) {
|
||||
|
||||
case base.SetParameter:
|
||||
if h, ok := sc.s.Handler.(ServerHandlerOnSetParameter); ok {
|
||||
pathAndQuery, ok := req.URL.RTSPPath()
|
||||
pathAndQuery, ok := req.URL.RTSPPathAndQuery()
|
||||
if !ok {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusBadRequest,
|
||||
|
@@ -422,7 +422,7 @@ func (ss *ServerSession) handleRequest(sc *ServerConn, req *base.Request) (*base
|
||||
}, err
|
||||
}
|
||||
|
||||
pathAndQuery, ok := req.URL.RTSPPath()
|
||||
pathAndQuery, ok := req.URL.RTSPPathAndQuery()
|
||||
if !ok {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusBadRequest,
|
||||
@@ -465,7 +465,7 @@ func (ss *ServerSession) handleRequest(sc *ServerConn, req *base.Request) (*base
|
||||
}, fmt.Errorf("unable to generate track URL")
|
||||
}
|
||||
|
||||
trackPath, ok := trackURL.RTSPPath()
|
||||
trackPath, ok := trackURL.RTSPPathAndQuery()
|
||||
if !ok {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusBadRequest,
|
||||
@@ -750,7 +750,7 @@ func (ss *ServerSession) handleRequest(sc *ServerConn, req *base.Request) (*base
|
||||
}, liberrors.ErrServerNoTracksSetup{}
|
||||
}
|
||||
|
||||
pathAndQuery, ok := req.URL.RTSPPath()
|
||||
pathAndQuery, ok := req.URL.RTSPPathAndQuery()
|
||||
if !ok {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusBadRequest,
|
||||
@@ -864,7 +864,7 @@ func (ss *ServerSession) handleRequest(sc *ServerConn, req *base.Request) (*base
|
||||
}, liberrors.ErrServerNotAllAnnouncedTracksSetup{}
|
||||
}
|
||||
|
||||
pathAndQuery, ok := req.URL.RTSPPath()
|
||||
pathAndQuery, ok := req.URL.RTSPPathAndQuery()
|
||||
if !ok {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusBadRequest,
|
||||
@@ -938,7 +938,7 @@ func (ss *ServerSession) handleRequest(sc *ServerConn, req *base.Request) (*base
|
||||
}, err
|
||||
}
|
||||
|
||||
pathAndQuery, ok := req.URL.RTSPPath()
|
||||
pathAndQuery, ok := req.URL.RTSPPathAndQuery()
|
||||
if !ok {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusBadRequest,
|
||||
@@ -997,7 +997,7 @@ func (ss *ServerSession) handleRequest(sc *ServerConn, req *base.Request) (*base
|
||||
|
||||
case base.GetParameter:
|
||||
if h, ok := sc.s.Handler.(ServerHandlerOnGetParameter); ok {
|
||||
pathAndQuery, ok := req.URL.RTSPPath()
|
||||
pathAndQuery, ok := req.URL.RTSPPathAndQuery()
|
||||
if !ok {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusBadRequest,
|
||||
|
Reference in New Issue
Block a user