alice-lg/pkg/http/api_validators.go
2023-05-12 14:37:28 +02:00

117 lines
2.8 KiB
Go

package http
import (
"fmt"
"strings"
"net/http"
)
// ErrValidationFailed indicates that a parameter validation
// failed and the response should be a BadRequest.
type ErrValidationFailed struct {
Param string `json:"param"`
Reason string `json:"reason"`
}
// Error implements the error interface
func (err *ErrValidationFailed) Error() string {
return err.Reason
}
// NewErrMissingParam returns a new error idicating
// a missing query parameter.
func NewErrMissingParam(key string) *ErrValidationFailed {
return &ErrValidationFailed{
Param: key,
Reason: fmt.Sprintf("query parameter %s is missing", key),
}
}
// NewErrAmbigousParam returns an ErrValidationFailed,
// indicating that the parameter was ambigous.
func NewErrAmbigousParam(key string) *ErrValidationFailed {
return &ErrValidationFailed{
Param: key,
Reason: fmt.Sprintf("query parameter %s is ambigous", key),
}
}
// NewErrEmptyParam return an ErrValidationFailed if the
// provided parameter value is empty.
func NewErrEmptyParam(key string) *ErrValidationFailed {
return &ErrValidationFailed{
Param: key,
Reason: fmt.Sprintf("query parameter %s is empty", key),
}
}
var (
// ErrQueryTooShort will be returned when the query
// is too short.
ErrQueryTooShort = &ErrValidationFailed{
"q", "the query is too short",
}
// ErrQueryIncomplete will be returned when the
// prefix query lacks a : or .
ErrQueryIncomplete = &ErrValidationFailed{
"q", "a prefix query must contain at least a '.' or ':'",
}
)
// Helper: Validate source Id
func validateSourceID(id string) (string, error) {
if len(id) > 42 {
return "unknown", &ErrValidationFailed{
Reason: fmt.Sprintf("source ID too long with length: %d", len(id)),
}
}
return id, nil
}
// Helper: Validate query string
func validateQueryString(req *http.Request, key string) (string, error) {
query := req.URL.Query()
values, ok := query[key]
if !ok {
return "", NewErrMissingParam(key)
}
if len(values) != 1 {
return "", NewErrAmbigousParam(key)
}
value := values[0]
if value == "" {
return "", NewErrEmptyParam(key)
}
return value, nil
}
// Helper: Validate prefix query. It should contain
// at least one dot or :
func validatePrefixQuery(value string) (string, error) {
// We should at least provide 2 chars
if len(value) < 2 {
return "", ErrQueryTooShort
}
if !strings.Contains(value, ":") && !strings.Contains(value, ".") {
return "", ErrQueryIncomplete
}
return value, nil
}
// Helper: Validate neighbors query. A valid query should have
// at least 4 chars.
func validateNeighborsQuery(value string) (string, error) {
if len(value) < 4 {
// TODO: Maybe make configurable
// Three letters tend to result in queries with too
// many results, which then leads to gateway timeouts.
return "", ErrQueryTooShort
}
return value, nil
}