Add multi-authentication support and comprehensive stream discovery

Major improvements to camera stream discovery system:

**Multi-Authentication Support:**
- Implement smart authentication fallback chain for HTTP/MJPEG/JPEG streams
- Add combined authentication method (Basic Auth header + query params) - fixes ZOSI cameras
- Support for: No Auth, Basic Auth, Query Params, Combined, Digest
- Auto-detect authentication method from URL and try appropriate chain

**Protocol & Detection Enhancements:**
- Add HLS (.m3u8) stream detection
- Add MPEG-DASH (.mpd) stream detection
- Add WebSocket stream detection
- Improve JPEG detection by URL extension when Content-Type is incorrect
- Add AuthMethod field to DiscoveredStream model

**Bug Fixes:**
- Fix port 0 bug: use default ports (HTTP=80, HTTPS=443, RTSP=554) when entry.Port==0
- Ensure URLs are built with correct ports from database or defaults

**Debug & Logging:**
- Add comprehensive DEBUG logging to builder.go (URL generation)
- Add comprehensive DEBUG logging to tester.go (stream testing & auth)
- Add comprehensive DEBUG logging to scanner.go (URL collection & deduplication)
- Log auth method detection, chain determination, and test results

**Results:**
- Tested with ZOSI ZG23213M camera: 4 streams found (was 0)
- Combined auth method successfully detects streams requiring both header + params
- Better coverage for cameras with non-standard authentication requirements

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
eduard256
2025-10-29 02:15:21 +03:00
parent bfade99c99
commit 453769a376
6 changed files with 514 additions and 25 deletions
+50 -1
View File
@@ -39,6 +39,16 @@ type BuildContext struct {
// BuildURL builds a complete URL from an entry and context
func (b *Builder) BuildURL(entry models.CameraEntry, ctx BuildContext) string {
b.logger.Debug("BuildURL called",
"entry_type", entry.Type,
"entry_url", entry.URL,
"entry_port", entry.Port,
"entry_protocol", entry.Protocol,
"ctx_ip", ctx.IP,
"ctx_port", ctx.Port,
"ctx_username", ctx.Username,
"ctx_channel", ctx.Channel)
// Set defaults
if ctx.Width == 0 {
ctx.Width = 640
@@ -50,6 +60,30 @@ func (b *Builder) BuildURL(entry models.CameraEntry, ctx BuildContext) string {
// Use entry's port if not specified
if ctx.Port == 0 {
ctx.Port = entry.Port
// If entry port is also 0, use default port for the protocol
if ctx.Port == 0 {
// Use entry's protocol if not specified for port determination
protocol := ctx.Protocol
if protocol == "" {
protocol = entry.Protocol
}
switch protocol {
case "http":
ctx.Port = 80
case "https":
ctx.Port = 443
case "rtsp", "rtsps":
ctx.Port = 554
default:
ctx.Port = 80 // Default to 80 if unknown
}
b.logger.Debug("using default port for protocol",
"protocol", protocol,
"default_port", ctx.Port)
}
}
// Use entry's protocol if not specified
@@ -59,12 +93,14 @@ func (b *Builder) BuildURL(entry models.CameraEntry, ctx BuildContext) string {
// Replace placeholders in URL path
path := b.replacePlaceholders(entry.URL, ctx)
b.logger.Debug("placeholders replaced", "original", entry.URL, "after_replacement", path)
// Build the complete URL
var fullURL string
// Check if the URL already contains authentication parameters
hasAuthInURL := b.hasAuthenticationParams(path)
b.logger.Debug("auth params detection", "has_auth_in_url", hasAuthInURL, "path", path)
switch ctx.Protocol {
case "rtsp":
@@ -112,7 +148,13 @@ func (b *Builder) BuildURL(entry models.CameraEntry, ctx BuildContext) string {
// Clean up double slashes (except after protocol://)
fullURL = b.cleanURL(fullURL)
b.logger.Debug("built stream URL", "url", fullURL, "entry", entry.Type)
b.logger.Debug("BuildURL complete",
"final_url", fullURL,
"entry_type", entry.Type,
"entry_url_pattern", entry.URL,
"protocol", ctx.Protocol,
"port", ctx.Port,
"has_auth_in_url", hasAuthInURL)
return fullURL
}
@@ -282,6 +324,7 @@ func (b *Builder) BuildURLsFromEntry(entry models.CameraEntry, ctx BuildContext)
// Build main URL
mainURL := b.BuildURL(entry, ctx)
b.logger.Debug("BuildURLsFromEntry: main URL built", "url", mainURL, "entry_type", entry.Type)
urls = append(urls, mainURL)
// For NVR systems, try multiple channels
@@ -317,5 +360,11 @@ func (b *Builder) BuildURLsFromEntry(entry models.CameraEntry, ctx BuildContext)
}
}
b.logger.Debug("BuildURLsFromEntry complete",
"entry_url_pattern", entry.URL,
"entry_type", entry.Type,
"total_urls_generated", len(urls),
"urls", urls)
return urls
}