4880e1ad14
Cameras under load may accept TCP connection but never respond, hanging tester workers indefinitely. Context timeout on the HTTP request ensures workers are released.
76 lines
1.8 KiB
Go
76 lines
1.8 KiB
Go
package tester
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/AlexxIT/go2rtc/pkg/core"
|
|
"github.com/AlexxIT/go2rtc/pkg/hls"
|
|
"github.com/AlexxIT/go2rtc/pkg/image"
|
|
"github.com/AlexxIT/go2rtc/pkg/magic"
|
|
"github.com/AlexxIT/go2rtc/pkg/mpjpeg"
|
|
"github.com/AlexxIT/go2rtc/pkg/tcp"
|
|
)
|
|
|
|
func init() {
|
|
RegisterSource("http", httpHandler)
|
|
RegisterSource("https", httpHandler)
|
|
RegisterSource("httpx", httpHandler)
|
|
}
|
|
|
|
// httpHandler -- HTTP GET with content-type detection.
|
|
// Supports JPEG snapshots, MJPEG streams, HLS, MPEG-TS, and auto-detect via magic.Open.
|
|
// Uses go2rtc tcp.Do for Basic + Digest auth and TLS handling.
|
|
// ex. "http://admin:pass@192.168.1.100/cgi-bin/snapshot.cgi"
|
|
func httpHandler(rawURL string) (core.Producer, error) {
|
|
rawURL, _, _ = strings.Cut(rawURL, "#")
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
|
|
|
req, err := http.NewRequestWithContext(ctx, "GET", rawURL, nil)
|
|
if err != nil {
|
|
cancel()
|
|
return nil, fmt.Errorf("http: request: %w", err)
|
|
}
|
|
|
|
res, err := tcp.Do(req)
|
|
if err != nil {
|
|
cancel()
|
|
return nil, fmt.Errorf("http: dial: %w", err)
|
|
}
|
|
|
|
if res.StatusCode != http.StatusOK {
|
|
cancel()
|
|
tcp.Close(res)
|
|
return nil, errors.New("http: " + res.Status)
|
|
}
|
|
|
|
// cancel on success is not called -- context expires naturally,
|
|
// connection lifetime is managed by prod.Stop()
|
|
|
|
ct := res.Header.Get("Content-Type")
|
|
if i := strings.IndexByte(ct, ';'); i > 0 {
|
|
ct = ct[:i]
|
|
}
|
|
|
|
var ext string
|
|
if i := strings.LastIndexByte(req.URL.Path, '.'); i > 0 {
|
|
ext = req.URL.Path[i+1:]
|
|
}
|
|
|
|
switch {
|
|
case ct == "application/vnd.apple.mpegurl" || ext == "m3u8":
|
|
return hls.OpenURL(req.URL, res.Body)
|
|
case ct == "image/jpeg":
|
|
return image.Open(res)
|
|
case ct == "multipart/x-mixed-replace":
|
|
return mpjpeg.Open(res.Body)
|
|
}
|
|
|
|
return magic.Open(res.Body)
|
|
}
|