Add support for HTTP over unix sockets (#4241)
This adds support for using unix scheme in xxxAddress config options. For example `hlsAddress: "unix://hls.sock"`. --------- Co-authored-by: aler9 <46489434+aler9@users.noreply.github.com>
This commit is contained in:
+2
-6
@@ -23,7 +23,6 @@ import (
|
||||
"github.com/bluenviron/mediamtx/internal/logger"
|
||||
"github.com/bluenviron/mediamtx/internal/protocols/httpp"
|
||||
"github.com/bluenviron/mediamtx/internal/recordstore"
|
||||
"github.com/bluenviron/mediamtx/internal/restrictnetwork"
|
||||
"github.com/bluenviron/mediamtx/internal/servers/hls"
|
||||
"github.com/bluenviron/mediamtx/internal/servers/rtmp"
|
||||
"github.com/bluenviron/mediamtx/internal/servers/rtsp"
|
||||
@@ -189,11 +188,8 @@ func (a *API) Initialize() error {
|
||||
group.GET("/recordings/get/*name", a.onRecordingsGet)
|
||||
group.DELETE("/recordings/deletesegment", a.onRecordingDeleteSegment)
|
||||
|
||||
network, address := restrictnetwork.Restrict("tcp", a.Address)
|
||||
|
||||
a.httpServer = &httpp.Server{
|
||||
Network: network,
|
||||
Address: address,
|
||||
Address: a.Address,
|
||||
ReadTimeout: time.Duration(a.ReadTimeout),
|
||||
Encryption: a.Encryption,
|
||||
ServerCert: a.ServerCert,
|
||||
@@ -206,7 +202,7 @@ func (a *API) Initialize() error {
|
||||
return err
|
||||
}
|
||||
|
||||
a.Log(logger.Info, "listener opened on "+address)
|
||||
a.Log(logger.Info, "listener opened on "+a.Address)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ import (
|
||||
"github.com/bluenviron/mediamtx/internal/defs"
|
||||
"github.com/bluenviron/mediamtx/internal/logger"
|
||||
"github.com/bluenviron/mediamtx/internal/protocols/httpp"
|
||||
"github.com/bluenviron/mediamtx/internal/restrictnetwork"
|
||||
)
|
||||
|
||||
func interfaceIsEmpty(i interface{}) bool {
|
||||
@@ -103,11 +102,8 @@ func (m *Metrics) Initialize() error {
|
||||
|
||||
router.GET("/metrics", m.onMetrics)
|
||||
|
||||
network, address := restrictnetwork.Restrict("tcp", m.Address)
|
||||
|
||||
m.httpServer = &httpp.Server{
|
||||
Network: network,
|
||||
Address: address,
|
||||
Address: m.Address,
|
||||
ReadTimeout: time.Duration(m.ReadTimeout),
|
||||
Encryption: m.Encryption,
|
||||
ServerCert: m.ServerCert,
|
||||
@@ -120,7 +116,7 @@ func (m *Metrics) Initialize() error {
|
||||
return err
|
||||
}
|
||||
|
||||
m.Log(logger.Info, "listener opened on "+address)
|
||||
m.Log(logger.Info, "listener opened on "+m.Address)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"github.com/bluenviron/mediamtx/internal/conf"
|
||||
"github.com/bluenviron/mediamtx/internal/logger"
|
||||
"github.com/bluenviron/mediamtx/internal/protocols/httpp"
|
||||
"github.com/bluenviron/mediamtx/internal/restrictnetwork"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
@@ -46,11 +45,8 @@ func (s *Server) Initialize() error {
|
||||
router.GET("/list", s.onList)
|
||||
router.GET("/get", s.onGet)
|
||||
|
||||
network, address := restrictnetwork.Restrict("tcp", s.Address)
|
||||
|
||||
s.httpServer = &httpp.Server{
|
||||
Network: network,
|
||||
Address: address,
|
||||
Address: s.Address,
|
||||
ReadTimeout: time.Duration(s.ReadTimeout),
|
||||
Encryption: s.Encryption,
|
||||
ServerCert: s.ServerCert,
|
||||
@@ -63,7 +59,7 @@ func (s *Server) Initialize() error {
|
||||
return err
|
||||
}
|
||||
|
||||
s.Log(logger.Info, "listener opened on "+address)
|
||||
s.Log(logger.Info, "listener opened on "+s.Address)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"github.com/bluenviron/mediamtx/internal/conf"
|
||||
"github.com/bluenviron/mediamtx/internal/logger"
|
||||
"github.com/bluenviron/mediamtx/internal/protocols/httpp"
|
||||
"github.com/bluenviron/mediamtx/internal/restrictnetwork"
|
||||
)
|
||||
|
||||
type pprofAuthManager interface {
|
||||
@@ -49,11 +48,8 @@ func (pp *PPROF) Initialize() error {
|
||||
|
||||
pprof.Register(router)
|
||||
|
||||
network, address := restrictnetwork.Restrict("tcp", pp.Address)
|
||||
|
||||
pp.httpServer = &httpp.Server{
|
||||
Network: network,
|
||||
Address: address,
|
||||
Address: pp.Address,
|
||||
ReadTimeout: time.Duration(pp.ReadTimeout),
|
||||
Encryption: pp.Encryption,
|
||||
ServerCert: pp.ServerCert,
|
||||
@@ -66,7 +62,7 @@ func (pp *PPROF) Initialize() error {
|
||||
return err
|
||||
}
|
||||
|
||||
pp.Log(logger.Info, "listener opened on "+address)
|
||||
pp.Log(logger.Info, "listener opened on "+pp.Address)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -8,10 +8,13 @@ import (
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/bluenviron/mediamtx/internal/certloader"
|
||||
"github.com/bluenviron/mediamtx/internal/logger"
|
||||
"github.com/bluenviron/mediamtx/internal/restrictnetwork"
|
||||
)
|
||||
|
||||
type nilWriter struct{}
|
||||
@@ -28,7 +31,6 @@ func (nilWriter) Write(p []byte) (int, error) {
|
||||
// - server header
|
||||
// - filtering of invalid requests
|
||||
type Server struct {
|
||||
Network string
|
||||
Address string
|
||||
ReadTimeout time.Duration
|
||||
Encryption bool
|
||||
@@ -65,12 +67,30 @@ func (s *Server) Initialize() error {
|
||||
}
|
||||
}
|
||||
|
||||
var network string
|
||||
var address string
|
||||
|
||||
if strings.HasPrefix(s.Address, "unix://") {
|
||||
network = "unix"
|
||||
address = s.Address[len("unix://"):]
|
||||
} else {
|
||||
network, address = restrictnetwork.Restrict("tcp", s.Address)
|
||||
}
|
||||
|
||||
if network == "unix" {
|
||||
os.Remove(address)
|
||||
}
|
||||
|
||||
var err error
|
||||
s.ln, err = net.Listen(s.Network, s.Address)
|
||||
s.ln, err = net.Listen(network, address)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if network == "unix" {
|
||||
os.Chmod(address, 0o755) //nolint:errcheck
|
||||
}
|
||||
|
||||
h := s.Handler
|
||||
h = &handlerFilterRequests{h}
|
||||
h = &handlerFilterRequests{h}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package httpp
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -13,10 +15,12 @@ import (
|
||||
|
||||
func TestFilterEmptyPath(t *testing.T) {
|
||||
s := &Server{
|
||||
Network: "tcp",
|
||||
Address: "localhost:4555",
|
||||
ReadTimeout: 10 * time.Second,
|
||||
Parent: test.NilLogger,
|
||||
Handler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}),
|
||||
}
|
||||
err := s.Initialize()
|
||||
require.NoError(t, err)
|
||||
@@ -26,13 +30,50 @@ func TestFilterEmptyPath(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
defer conn.Close()
|
||||
|
||||
_, err = conn.Write([]byte("OPTIONS http://localhost HTTP/1.1\n" +
|
||||
"Host: localhost:8889\n" +
|
||||
"Accept-Encoding: gzip\n" +
|
||||
"User-Agent: Go-http-client/1.1\n\n"))
|
||||
_, err = conn.Write([]byte("OPTIONS / HTTP/1.1\n" +
|
||||
"Host: localhost:8889\n\n"))
|
||||
require.NoError(t, err)
|
||||
|
||||
buf := make([]byte, 20)
|
||||
_, err = io.ReadFull(conn, buf)
|
||||
buf := make([]byte, 200)
|
||||
n, err := conn.Read(buf)
|
||||
require.NoError(t, err)
|
||||
|
||||
res := strings.Split(string(buf[:n]), "\r\n")
|
||||
require.Equal(t, "HTTP/1.1 200 OK", res[0])
|
||||
}
|
||||
|
||||
func TestUnixSocket(t *testing.T) {
|
||||
s := &Server{
|
||||
Address: "unix://http.sock",
|
||||
ReadTimeout: 10 * time.Second,
|
||||
Parent: test.NilLogger,
|
||||
Handler: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}),
|
||||
}
|
||||
err := s.Initialize()
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = os.Stat("http.sock")
|
||||
require.NoError(t, err)
|
||||
|
||||
conn, err := net.Dial("unix", "http.sock")
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = conn.Write([]byte("OPTIONS / HTTP/1.1\n" +
|
||||
"Host: localhost:8889\n\n"))
|
||||
require.NoError(t, err)
|
||||
|
||||
buf := make([]byte, 200)
|
||||
n, err := conn.Read(buf)
|
||||
require.NoError(t, err)
|
||||
|
||||
res := strings.Split(string(buf[:n]), "\r\n")
|
||||
require.Equal(t, "HTTP/1.1 200 OK", res[0])
|
||||
|
||||
conn.Close()
|
||||
s.Close()
|
||||
|
||||
_, err = os.Stat("http.sock")
|
||||
require.EqualError(t, err, "stat http.sock: no such file or directory")
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ import (
|
||||
"github.com/bluenviron/mediamtx/internal/defs"
|
||||
"github.com/bluenviron/mediamtx/internal/logger"
|
||||
"github.com/bluenviron/mediamtx/internal/protocols/httpp"
|
||||
"github.com/bluenviron/mediamtx/internal/restrictnetwork"
|
||||
)
|
||||
|
||||
//go:generate go run ./hlsjsdownloader
|
||||
@@ -57,11 +56,8 @@ func (s *httpServer) initialize() error {
|
||||
|
||||
router.Use(s.onRequest)
|
||||
|
||||
network, address := restrictnetwork.Restrict("tcp", s.address)
|
||||
|
||||
s.inner = &httpp.Server{
|
||||
Network: network,
|
||||
Address: address,
|
||||
Address: s.address,
|
||||
ReadTimeout: time.Duration(s.readTimeout),
|
||||
Encryption: s.encryption,
|
||||
ServerCert: s.serverCert,
|
||||
|
||||
@@ -20,7 +20,6 @@ import (
|
||||
"github.com/bluenviron/mediamtx/internal/logger"
|
||||
"github.com/bluenviron/mediamtx/internal/protocols/httpp"
|
||||
"github.com/bluenviron/mediamtx/internal/protocols/whip"
|
||||
"github.com/bluenviron/mediamtx/internal/restrictnetwork"
|
||||
)
|
||||
|
||||
//go:embed publish_index.html
|
||||
@@ -94,11 +93,8 @@ func (s *httpServer) initialize() error {
|
||||
|
||||
router.Use(s.onRequest)
|
||||
|
||||
network, address := restrictnetwork.Restrict("tcp", s.address)
|
||||
|
||||
s.inner = &httpp.Server{
|
||||
Network: network,
|
||||
Address: address,
|
||||
Address: s.address,
|
||||
ReadTimeout: time.Duration(s.readTimeout),
|
||||
Encryption: s.encryption,
|
||||
ServerCert: s.serverCert,
|
||||
|
||||
Reference in New Issue
Block a user