feat(config): tighten RTMP URL validation
Some checks failed
ci-build / lint (push) Has been cancelled
ci-build / build (push) Has been cancelled
ci-build / release (push) Has been cancelled

This commit is contained in:
Rob Watson 2025-04-10 22:00:37 +02:00
parent 045498a2ce
commit b257f456ba
5 changed files with 27 additions and 11 deletions

View File

@ -325,7 +325,7 @@ func TestIntegrationDestinationValidations(t *testing.T) {
contents := getContents()
assert.True(t, contentsIncludes(contents, "Configuration update failed:"), "expected to see config update error")
assert.True(t, contentsIncludes(contents, "validate: destination URL must start with"), "expected to see config update error")
assert.True(t, contentsIncludes(contents, "validate: destination URL must be an RTMP URL"), "expected to see invalid RTMP URL error")
},
10*time.Second,
time.Second,
@ -345,7 +345,7 @@ func TestIntegrationDestinationValidations(t *testing.T) {
contents := getContents()
assert.True(t, contentsIncludes(contents, "Configuration update failed:"), "expected to see config update error")
assert.True(t, contentsIncludes(contents, "validate: destination URL must start with"), "expected to see config update error")
assert.True(t, contentsIncludes(contents, "validate: destination URL must be an RTMP URL"), "expected to see invalid RTMP URL error")
},
10*time.Second,
time.Second,

View File

@ -5,9 +5,9 @@ import (
_ "embed"
"errors"
"fmt"
"net/url"
"os"
"path/filepath"
"strings"
"gopkg.in/yaml.v3"
)
@ -204,8 +204,10 @@ func validate(cfg Config) error {
urlCounts := make(map[string]int)
for _, dest := range cfg.Destinations {
if !strings.HasPrefix(dest.URL, "rtmp://") {
err = errors.Join(err, fmt.Errorf("destination URL must start with rtmp://"))
if u, urlErr := url.Parse(dest.URL); urlErr != nil {
err = errors.Join(err, fmt.Errorf("invalid destination URL: %w", urlErr))
} else if u.Scheme != "rtmp" {
err = errors.Join(err, errors.New("destination URL must be an RTMP URL"))
}
urlCounts[dest.URL]++

View File

@ -25,8 +25,11 @@ var configLogfile []byte
//go:embed testdata/no-logfile.yml
var configNoLogfile []byte
//go:embed testdata/invalid-destination-url.yml
var configInvalidDestinationURL []byte
//go:embed testdata/destination-url-not-rtmp.yml
var configDestinationURLNotRTMP []byte
//go:embed testdata/destination-url-not-valid.yml
var configDestinationURLNotValid []byte
//go:embed testdata/multiple-invalid-destination-urls.yml
var configMultipleInvalidDestinationURLs []byte
@ -120,14 +123,19 @@ func TestConfigServiceReadConfig(t *testing.T) {
},
},
{
name: "invalid destination URL",
configBytes: configInvalidDestinationURL,
wantErr: "destination URL must start with rtmp://",
name: "destination URL is not rtmp scheme",
configBytes: configDestinationURLNotRTMP,
wantErr: "destination URL must be an RTMP URL",
},
{
name: "destination URL is not valid",
configBytes: configDestinationURLNotValid,
wantErr: `invalid destination URL: parse "rtmp://rtmp.example.com/%%+": invalid URL escape "%%+"`,
},
{
name: "multiple invalid destination URLs",
configBytes: configMultipleInvalidDestinationURLs,
wantErr: "destination URL must start with rtmp://\ndestination URL must start with rtmp://",
wantErr: "destination URL must be an RTMP URL\ndestination URL must be an RTMP URL",
},
}

View File

@ -0,0 +1,6 @@
---
logfile:
enabled: true
path: test.log
destinations:
- url: rtmp://rtmp.example.com/%%+