Files
Strix/internal/go2rtc/go2rtc.go
T

109 lines
2.2 KiB
Go

package go2rtc
import (
"io"
"net/http"
"sync"
"time"
"github.com/eduard256/strix/internal/api"
"github.com/eduard256/strix/internal/app"
"github.com/rs/zerolog"
)
var log zerolog.Logger
var go2rtcURL string
var go2rtcOnce sync.Once
var candidates = []string{
"http://localhost:1984",
"http://localhost:11984",
}
const probeTimeout = 50 * time.Millisecond
const requestTimeout = 5 * time.Second
func Init() {
log = app.GetLogger("go2rtc")
if url := app.Env("STRIX_GO2RTC_URL", ""); url != "" {
go2rtcURL = url
log.Info().Str("url", go2rtcURL).Msg("[go2rtc] using STRIX_GO2RTC_URL")
}
api.HandleFunc("api/go2rtc/streams", apiStreams)
}
func getURL() string {
if go2rtcURL != "" {
return go2rtcURL
}
go2rtcOnce.Do(func() {
go2rtcURL = probe()
if go2rtcURL != "" {
log.Info().Str("url", go2rtcURL).Msg("[go2rtc] discovered")
}
})
return go2rtcURL
}
func probe() string {
client := &http.Client{Timeout: probeTimeout}
for _, url := range candidates {
resp, err := client.Get(url + "/api")
if err != nil {
continue
}
resp.Body.Close()
if resp.StatusCode == 200 {
return url
}
}
return ""
}
// PUT /api/go2rtc/streams?name=...&src=... -- proxy to go2rtc
func apiStreams(w http.ResponseWriter, r *http.Request) {
if r.Method != "PUT" {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
url := getURL()
if url == "" {
api.ResponseJSON(w, map[string]any{"success": false, "error": "go2rtc not found"})
return
}
// forward query params as-is
target := url + "/api/streams?" + r.URL.RawQuery
client := &http.Client{Timeout: requestTimeout}
req, err := http.NewRequest("PUT", target, nil)
if err != nil {
api.ResponseJSON(w, map[string]any{"success": false, "error": err.Error()})
return
}
resp, err := client.Do(req)
if err != nil {
api.ResponseJSON(w, map[string]any{"success": false, "error": err.Error()})
return
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
w.Header().Set("Content-Type", "application/json")
if resp.StatusCode == 200 {
api.ResponseJSON(w, map[string]any{"success": true})
} else {
api.ResponseJSON(w, map[string]any{"success": false, "error": string(body)})
}
}