mirror of
https://github.com/aler9/gortsplib
synced 2025-10-12 02:20:19 +08:00
support unencoded symbols in urls (https://github.com/aler9/rtsp-simple-server/issues/100)
This commit is contained in:
@@ -121,6 +121,7 @@ func (req Request) Write(bw *bufio.Writer) error {
|
|||||||
Scheme: req.Url.Scheme,
|
Scheme: req.Url.Scheme,
|
||||||
Host: req.Url.Host,
|
Host: req.Url.Host,
|
||||||
Path: req.Url.Path,
|
Path: req.Url.Path,
|
||||||
|
RawPath: req.Url.RawPath,
|
||||||
RawQuery: req.Url.RawQuery,
|
RawQuery: req.Url.RawQuery,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -9,6 +9,14 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func mustParseUrl(s string) *url.URL {
|
||||||
|
u, err := url.Parse(s)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
var casesRequest = []struct {
|
var casesRequest = []struct {
|
||||||
name string
|
name string
|
||||||
byts []byte
|
byts []byte
|
||||||
@@ -23,7 +31,7 @@ var casesRequest = []struct {
|
|||||||
"\r\n"),
|
"\r\n"),
|
||||||
Request{
|
Request{
|
||||||
Method: "OPTIONS",
|
Method: "OPTIONS",
|
||||||
Url: &url.URL{Scheme: "rtsp", Host: "example.com", Path: "/media.mp4"},
|
Url: mustParseUrl("rtsp://example.com/media.mp4"),
|
||||||
Header: Header{
|
Header: Header{
|
||||||
"CSeq": HeaderValue{"1"},
|
"CSeq": HeaderValue{"1"},
|
||||||
"Require": HeaderValue{"implicit-play"},
|
"Require": HeaderValue{"implicit-play"},
|
||||||
@@ -34,13 +42,30 @@ var casesRequest = []struct {
|
|||||||
{
|
{
|
||||||
"describe",
|
"describe",
|
||||||
[]byte("DESCRIBE rtsp://example.com/media.mp4 RTSP/1.0\r\n" +
|
[]byte("DESCRIBE rtsp://example.com/media.mp4 RTSP/1.0\r\n" +
|
||||||
|
"Accept: application/sdp\r\n" +
|
||||||
"CSeq: 2\r\n" +
|
"CSeq: 2\r\n" +
|
||||||
"\r\n"),
|
"\r\n"),
|
||||||
Request{
|
Request{
|
||||||
Method: "DESCRIBE",
|
Method: "DESCRIBE",
|
||||||
Url: &url.URL{Scheme: "rtsp", Host: "example.com", Path: "/media.mp4"},
|
Url: mustParseUrl("rtsp://example.com/media.mp4"),
|
||||||
Header: Header{
|
Header: Header{
|
||||||
"CSeq": HeaderValue{"2"},
|
"Accept": HeaderValue{"application/sdp"},
|
||||||
|
"CSeq": HeaderValue{"2"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"describe with exclamation mark",
|
||||||
|
[]byte("DESCRIBE rtsp://192.168.1.99:554/user=tmp&password=BagRep1!&channel=1&stream=0.sdp RTSP/1.0\r\n" +
|
||||||
|
"Accept: application/sdp\r\n" +
|
||||||
|
"CSeq: 3\r\n" +
|
||||||
|
"\r\n"),
|
||||||
|
Request{
|
||||||
|
Method: "DESCRIBE",
|
||||||
|
Url: mustParseUrl("rtsp://192.168.1.99:554/user=tmp&password=BagRep1!&channel=1&stream=0.sdp"),
|
||||||
|
Header: Header{
|
||||||
|
"Accept": HeaderValue{"application/sdp"},
|
||||||
|
"CSeq": HeaderValue{"3"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -66,7 +91,7 @@ var casesRequest = []struct {
|
|||||||
"m=video 2232 RTP/AVP 31\n"),
|
"m=video 2232 RTP/AVP 31\n"),
|
||||||
Request{
|
Request{
|
||||||
Method: "ANNOUNCE",
|
Method: "ANNOUNCE",
|
||||||
Url: &url.URL{Scheme: "rtsp", Host: "example.com", Path: "/media.mp4"},
|
Url: mustParseUrl("rtsp://example.com/media.mp4"),
|
||||||
Header: Header{
|
Header: Header{
|
||||||
"CSeq": HeaderValue{"7"},
|
"CSeq": HeaderValue{"7"},
|
||||||
"Date": HeaderValue{"23 Jan 1997 15:35:06 GMT"},
|
"Date": HeaderValue{"23 Jan 1997 15:35:06 GMT"},
|
||||||
@@ -100,7 +125,7 @@ var casesRequest = []struct {
|
|||||||
"jitter\n"),
|
"jitter\n"),
|
||||||
Request{
|
Request{
|
||||||
Method: "GET_PARAMETER",
|
Method: "GET_PARAMETER",
|
||||||
Url: &url.URL{Scheme: "rtsp", Host: "example.com", Path: "/media.mp4"},
|
Url: mustParseUrl("rtsp://example.com/media.mp4"),
|
||||||
Header: Header{
|
Header: Header{
|
||||||
"CSeq": HeaderValue{"9"},
|
"CSeq": HeaderValue{"9"},
|
||||||
"Content-Type": HeaderValue{"text/parameters"},
|
"Content-Type": HeaderValue{"text/parameters"},
|
||||||
|
@@ -281,6 +281,7 @@ func (c *ConnClient) Do(req *base.Request) (*base.Response, error) {
|
|||||||
Scheme: req.Url.Scheme,
|
Scheme: req.Url.Scheme,
|
||||||
Host: req.Url.Host,
|
Host: req.Url.Host,
|
||||||
Path: req.Url.Path,
|
Path: req.Url.Path,
|
||||||
|
RawPath: req.Url.RawPath,
|
||||||
RawQuery: req.Url.RawQuery,
|
RawQuery: req.Url.RawQuery,
|
||||||
}
|
}
|
||||||
req.Header["Authorization"] = c.auth.GenerateHeader(req.Method, u)
|
req.Header["Authorization"] = c.auth.GenerateHeader(req.Method, u)
|
||||||
@@ -446,6 +447,7 @@ func (c *ConnClient) urlForTrack(baseUrl *url.URL, mode TransportMode, track *Tr
|
|||||||
Host: baseUrl.Host,
|
Host: baseUrl.Host,
|
||||||
User: baseUrl.User,
|
User: baseUrl.User,
|
||||||
Path: newUrl.Path,
|
Path: newUrl.Path,
|
||||||
|
RawPath: newUrl.RawPath,
|
||||||
RawQuery: newUrl.RawQuery,
|
RawQuery: newUrl.RawQuery,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -456,14 +458,23 @@ func (c *ConnClient) urlForTrack(baseUrl *url.URL, mode TransportMode, track *Tr
|
|||||||
Host: baseUrl.Host,
|
Host: baseUrl.Host,
|
||||||
User: baseUrl.User,
|
User: baseUrl.User,
|
||||||
Path: baseUrl.Path,
|
Path: baseUrl.Path,
|
||||||
|
RawPath: baseUrl.RawPath,
|
||||||
RawQuery: baseUrl.RawQuery,
|
RawQuery: baseUrl.RawQuery,
|
||||||
}
|
}
|
||||||
// insert the control attribute after the query, if present
|
|
||||||
|
// insert the control at the end of the url
|
||||||
if u.RawQuery != "" {
|
if u.RawQuery != "" {
|
||||||
if !strings.HasSuffix(u.RawQuery, "/") {
|
if !strings.HasSuffix(u.RawQuery, "/") {
|
||||||
u.RawQuery += "/"
|
u.RawQuery += "/"
|
||||||
}
|
}
|
||||||
u.RawQuery += control
|
u.RawQuery += control
|
||||||
|
|
||||||
|
} else if u.RawPath != "" {
|
||||||
|
if !strings.HasSuffix(u.RawPath, "/") {
|
||||||
|
u.RawPath += "/"
|
||||||
|
}
|
||||||
|
u.RawPath += control
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if !strings.HasSuffix(u.Path, "/") {
|
if !strings.HasSuffix(u.Path, "/") {
|
||||||
u.Path += "/"
|
u.Path += "/"
|
||||||
@@ -782,7 +793,8 @@ func (c *ConnClient) LoopUDP() error {
|
|||||||
Host: c.streamUrl.Host,
|
Host: c.streamUrl.Host,
|
||||||
User: c.streamUrl.User,
|
User: c.streamUrl.User,
|
||||||
// use the stream path, otherwise some cameras do not reply
|
// use the stream path, otherwise some cameras do not reply
|
||||||
Path: c.streamUrl.Path,
|
Path: c.streamUrl.Path,
|
||||||
|
RawPath: c.streamUrl.RawPath,
|
||||||
},
|
},
|
||||||
SkipResponse: true,
|
SkipResponse: true,
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user