117 lines
2.8 KiB
Go
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
|
|
}
|