Phase 2: Subsonic REST API framework (auth, response formatting, error handling, routing) plus user permission model

This commit is contained in:
2026-08-22 23:58:54 -05:00
parent f81c8704a5
commit b5e2bf01e2
26 changed files with 1772 additions and 75 deletions
+82
View File
@@ -0,0 +1,82 @@
package subsonic
import (
"net/url"
"strconv"
)
// params wraps the request's merged query+form values with typed,
// error-producing accessors, so handlers never hand-roll parameter
// parsing/validation.
type params struct {
values url.Values
}
func (p params) Get(name string) string {
return p.values.Get(name)
}
func (p params) GetAll(name string) []string {
return p.values[name]
}
func (p params) Has(name string) bool {
_, ok := p.values[name]
return ok
}
func (p params) Required(name string) (string, *apiError) {
v := p.values.Get(name)
if v == "" {
return "", errMissingParameter(name)
}
return v, nil
}
func (p params) Int(name string, def int) int {
v := p.values.Get(name)
if v == "" {
return def
}
n, err := strconv.Atoi(v)
if err != nil {
return def
}
return n
}
func (p params) RequiredInt(name string) (int, *apiError) {
v := p.values.Get(name)
if v == "" {
return 0, errMissingParameter(name)
}
n, err := strconv.Atoi(v)
if err != nil {
return 0, errMissingParameter(name)
}
return n, nil
}
func (p params) Int64(name string, def int64) int64 {
v := p.values.Get(name)
if v == "" {
return def
}
n, err := strconv.ParseInt(v, 10, 64)
if err != nil {
return def
}
return n
}
func (p params) Bool(name string, def bool) bool {
v := p.values.Get(name)
if v == "" {
return def
}
b, err := strconv.ParseBool(v)
if err != nil {
return def
}
return b
}