Fix URL parameter replacement logic to preserve literal values
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
package stream
|
package stream
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
"regexp"
|
"regexp"
|
||||||
@@ -56,6 +57,8 @@ func (b *Builder) BuildURL(entry models.CameraEntry, ctx BuildContext) string {
|
|||||||
if ctx.Height == 0 {
|
if ctx.Height == 0 {
|
||||||
ctx.Height = 480
|
ctx.Height = 480
|
||||||
}
|
}
|
||||||
|
// NOTE: Channel default is 0 - will only be used for [CHANNEL] placeholder replacement
|
||||||
|
// Literal channel values in URLs (like "channel=1") are preserved as-is
|
||||||
|
|
||||||
// Use entry's port if not specified
|
// Use entry's port if not specified
|
||||||
if ctx.Port == 0 {
|
if ctx.Port == 0 {
|
||||||
@@ -163,6 +166,12 @@ func (b *Builder) BuildURL(entry models.CameraEntry, ctx BuildContext) string {
|
|||||||
func (b *Builder) replacePlaceholders(urlPath string, ctx BuildContext) string {
|
func (b *Builder) replacePlaceholders(urlPath string, ctx BuildContext) string {
|
||||||
result := urlPath
|
result := urlPath
|
||||||
|
|
||||||
|
// Generate base64 auth for [AUTH] placeholder
|
||||||
|
auth := ""
|
||||||
|
if ctx.Username != "" && ctx.Password != "" {
|
||||||
|
auth = base64.StdEncoding.EncodeToString([]byte(ctx.Username + ":" + ctx.Password))
|
||||||
|
}
|
||||||
|
|
||||||
// Common placeholders
|
// Common placeholders
|
||||||
replacements := map[string]string{
|
replacements := map[string]string{
|
||||||
"[CHANNEL]": strconv.Itoa(ctx.Channel),
|
"[CHANNEL]": strconv.Itoa(ctx.Channel),
|
||||||
@@ -187,6 +196,8 @@ func (b *Builder) replacePlaceholders(urlPath string, ctx BuildContext) string {
|
|||||||
"[ip]": ctx.IP,
|
"[ip]": ctx.IP,
|
||||||
"[PORT]": strconv.Itoa(ctx.Port),
|
"[PORT]": strconv.Itoa(ctx.Port),
|
||||||
"[port]": strconv.Itoa(ctx.Port),
|
"[port]": strconv.Itoa(ctx.Port),
|
||||||
|
"[AUTH]": auth, // base64(username:password) for basic auth
|
||||||
|
"[auth]": auth,
|
||||||
"[TOKEN]": "", // Empty for now
|
"[TOKEN]": "", // Empty for now
|
||||||
"[token]": "",
|
"[token]": "",
|
||||||
}
|
}
|
||||||
@@ -196,41 +207,12 @@ func (b *Builder) replacePlaceholders(urlPath string, ctx BuildContext) string {
|
|||||||
result = strings.ReplaceAll(result, placeholder, value)
|
result = strings.ReplaceAll(result, placeholder, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle {var} style placeholders
|
// Handle query parameter placeholders (only for auth params)
|
||||||
result = b.replaceVarPlaceholders(result, ctx)
|
|
||||||
|
|
||||||
// Handle query parameter placeholders
|
|
||||||
result = b.replaceQueryParams(result, ctx)
|
result = b.replaceQueryParams(result, ctx)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// replaceVarPlaceholders replaces {var} style placeholders
|
|
||||||
func (b *Builder) replaceVarPlaceholders(urlPath string, ctx BuildContext) string {
|
|
||||||
varPattern := regexp.MustCompile(`\{([^}]+)\}`)
|
|
||||||
|
|
||||||
return varPattern.ReplaceAllStringFunc(urlPath, func(match string) string {
|
|
||||||
key := strings.Trim(match, "{}")
|
|
||||||
switch strings.ToLower(key) {
|
|
||||||
case "username", "user":
|
|
||||||
return ctx.Username
|
|
||||||
case "password", "pass", "pwd":
|
|
||||||
return ctx.Password
|
|
||||||
case "ip":
|
|
||||||
return ctx.IP
|
|
||||||
case "port":
|
|
||||||
return strconv.Itoa(ctx.Port)
|
|
||||||
case "channel", "chn", "ch":
|
|
||||||
return strconv.Itoa(ctx.Channel)
|
|
||||||
case "width":
|
|
||||||
return strconv.Itoa(ctx.Width)
|
|
||||||
case "height":
|
|
||||||
return strconv.Itoa(ctx.Height)
|
|
||||||
default:
|
|
||||||
return match // Keep original if not recognized
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// replaceQueryParams handles query parameter replacements
|
// replaceQueryParams handles query parameter replacements
|
||||||
func (b *Builder) replaceQueryParams(urlPath string, ctx BuildContext) string {
|
func (b *Builder) replaceQueryParams(urlPath string, ctx BuildContext) string {
|
||||||
@@ -249,24 +231,17 @@ func (b *Builder) replaceQueryParams(urlPath string, ctx BuildContext) string {
|
|||||||
return urlPath
|
return urlPath
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace known parameter values
|
// ONLY replace authentication parameters
|
||||||
|
// DO NOT replace channel, width, height - they should stay as-is from URL patterns
|
||||||
for key := range params {
|
for key := range params {
|
||||||
lowerKey := strings.ToLower(key)
|
lowerKey := strings.ToLower(key)
|
||||||
|
|
||||||
// Check if this is a known parameter from our list
|
switch lowerKey {
|
||||||
if b.isKnownParameter(lowerKey) {
|
case "user", "username", "usr", "loginuse":
|
||||||
switch lowerKey {
|
params.Set(key, ctx.Username)
|
||||||
case "user", "username", "usr", "loginuse":
|
case "password", "pass", "pwd", "loginpas", "passwd":
|
||||||
params.Set(key, ctx.Username)
|
params.Set(key, ctx.Password)
|
||||||
case "password", "pass", "pwd", "loginpas", "passwd":
|
// Removed: channel, width, height replacements - they were breaking working URLs
|
||||||
params.Set(key, ctx.Password)
|
|
||||||
case "channel", "chn", "ch":
|
|
||||||
params.Set(key, strconv.Itoa(ctx.Channel))
|
|
||||||
case "width":
|
|
||||||
params.Set(key, strconv.Itoa(ctx.Width))
|
|
||||||
case "height":
|
|
||||||
params.Set(key, strconv.Itoa(ctx.Height))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,15 +249,6 @@ func (b *Builder) replaceQueryParams(urlPath string, ctx BuildContext) string {
|
|||||||
return basePath + "?" + params.Encode()
|
return basePath + "?" + params.Encode()
|
||||||
}
|
}
|
||||||
|
|
||||||
// isKnownParameter checks if a parameter is in our known list
|
|
||||||
func (b *Builder) isKnownParameter(param string) bool {
|
|
||||||
for _, known := range b.queryParams {
|
|
||||||
if strings.ToLower(known) == param {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// hasAuthenticationParams checks if URL contains auth parameters
|
// hasAuthenticationParams checks if URL contains auth parameters
|
||||||
func (b *Builder) hasAuthenticationParams(urlPath string) bool {
|
func (b *Builder) hasAuthenticationParams(urlPath string) bool {
|
||||||
|
|||||||
Reference in New Issue
Block a user