Files
spsays-bff/pkg/shorturl/validate.go
2026-05-11 16:13:22 +05:30

43 lines
1.1 KiB
Go

package shorturl
import (
"fmt"
"strings"
)
// MaxPathLength caps the long URL length we'll accept. 2KB is well beyond any
// real `?hl=` URL we generate while preventing pathological storage abuse.
const MaxPathLength = 2048
// ValidatePath verifies that s is a same-site relative URL — starts with "/",
// no scheme/host, no NUL bytes, within length. Prevents using the shortener
// as an open redirect to arbitrary external domains.
func ValidatePath(s string) error {
if s == "" {
return fmt.Errorf("url is empty")
}
if len(s) > MaxPathLength {
return fmt.Errorf("url exceeds %d bytes", MaxPathLength)
}
if !strings.HasPrefix(s, "/") {
return fmt.Errorf("url must start with '/'")
}
// "//host/…" is protocol-relative — disallow.
if strings.HasPrefix(s, "//") {
return fmt.Errorf("url must not be protocol-relative")
}
if strings.ContainsRune(s, 0) {
return fmt.Errorf("url contains NUL byte")
}
// No scheme allowed: scan up to the first '/' or '?' for ':'.
for i, c := range s {
if c == '?' || c == '#' {
break
}
if c == ':' && i > 0 {
return fmt.Errorf("url must not contain a scheme")
}
}
return nil
}