From d59cb99f0d54422a8af3d9dc5e2931f7cedb1a70 Mon Sep 17 00:00:00 2001 From: Alex X Date: Wed, 15 Oct 2025 14:09:07 +0300 Subject: [PATCH] Support RTSP redirects #1909 by @eddielth --- pkg/rtsp/client.go | 36 ++++++++++++++++++++++++++++++------ pkg/tcp/auth.go | 4 ++++ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/pkg/rtsp/client.go b/pkg/rtsp/client.go index 4e891213..c9607321 100644 --- a/pkg/rtsp/client.go +++ b/pkg/rtsp/client.go @@ -93,7 +93,35 @@ func (c *Conn) Do(req *tcp.Request) (*tcp.Response, error) { c.Fire(res) - if res.StatusCode == http.StatusUnauthorized { + switch res.StatusCode { + case http.StatusOK: + return res, nil + + case http.StatusMovedPermanently, http.StatusFound: + rawURL := res.Header.Get("Location") + + var u *url.URL + if u, err = url.Parse(rawURL); err != nil { + return nil, err + } + + if u.User == nil { + u.User = c.auth.UserInfo() // restore auth if we don't have it in the new URL + } + + c.uri = u.String() // so auth will be saved on reconnect + + _ = c.conn.Close() + + if err = c.Dial(); err != nil { + return nil, err + } + + req.URL = c.URL // because path was changed + + return c.Do(req) + + case http.StatusUnauthorized: switch c.auth.Method { case tcp.AuthNone: if c.auth.ReadNone(res) { @@ -109,11 +137,7 @@ func (c *Conn) Do(req *tcp.Request) (*tcp.Response, error) { } } - if res.StatusCode != http.StatusOK { - return res, fmt.Errorf("wrong response on %s", req.Method) - } - - return res, nil + return res, fmt.Errorf("wrong response on %s", req.Method) } func (c *Conn) Options() error { diff --git a/pkg/tcp/auth.go b/pkg/tcp/auth.go index 3eb26024..9cc56ba2 100644 --- a/pkg/tcp/auth.go +++ b/pkg/tcp/auth.go @@ -112,6 +112,10 @@ func (a *Auth) ReadNone(res *Response) bool { return false } +func (a *Auth) UserInfo() *url.Userinfo { + return url.UserPassword(a.user, a.pass) +} + func Between(s, sub1, sub2 string) string { i := strings.Index(s, sub1) if i < 0 {