Finish up better parsing
This commit is contained in:
parent
574e72a974
commit
1f6118f068
7 changed files with 443 additions and 395 deletions
107
server/util.go
107
server/util.go
|
@ -1,17 +1,10 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"heckel.io/ntfy/util"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
actionIDLength = 10
|
||||
actionsMax = 3
|
||||
)
|
||||
|
||||
func readBoolParam(r *http.Request, defaultValue bool, names ...string) bool {
|
||||
value := strings.ToLower(readParam(r, names...))
|
||||
if value == "" {
|
||||
|
@ -47,103 +40,3 @@ func readQueryParam(r *http.Request, names ...string) string {
|
|||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func parseActions(s string) (actions []*action, err error) {
|
||||
// Parse JSON or simple format
|
||||
s = strings.TrimSpace(s)
|
||||
if strings.HasPrefix(s, "[") {
|
||||
actions, err = parseActionsFromJSON(s)
|
||||
} else {
|
||||
actions, err = parseActionsFromSimpleNew(s)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Add ID field, ensure correct uppercase/lowercase
|
||||
for i := range actions {
|
||||
actions[i].ID = util.RandomString(actionIDLength)
|
||||
actions[i].Action = strings.ToLower(actions[i].Action)
|
||||
actions[i].Method = strings.ToUpper(actions[i].Method)
|
||||
}
|
||||
|
||||
// Validate
|
||||
if len(actions) > actionsMax {
|
||||
return nil, wrapErrHTTP(errHTTPBadRequestActionsInvalid, "only %d actions allowed", actionsMax)
|
||||
}
|
||||
for _, action := range actions {
|
||||
if !util.InStringList([]string{"view", "broadcast", "http"}, action.Action) {
|
||||
return nil, wrapErrHTTP(errHTTPBadRequestActionsInvalid, "action '%s' unknown", action.Action)
|
||||
} else if action.Label == "" {
|
||||
return nil, wrapErrHTTP(errHTTPBadRequestActionsInvalid, "parameter 'label' is required")
|
||||
} else if util.InStringList([]string{"view", "http"}, action.Action) && action.URL == "" {
|
||||
return nil, wrapErrHTTP(errHTTPBadRequestActionsInvalid, "parameter 'url' is required for action '%s'", action.Action)
|
||||
} else if action.Action == "http" && util.InStringList([]string{"GET", "HEAD"}, action.Method) && action.Body != "" {
|
||||
return nil, wrapErrHTTP(errHTTPBadRequestActionsInvalid, "parameter 'body' cannot be set if method is %s", action.Method)
|
||||
}
|
||||
}
|
||||
|
||||
return actions, nil
|
||||
}
|
||||
|
||||
func parseActionsFromJSON(s string) ([]*action, error) {
|
||||
actions := make([]*action, 0)
|
||||
if err := json.Unmarshal([]byte(s), &actions); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return actions, nil
|
||||
}
|
||||
|
||||
func parseActionsFromSimple(s string) ([]*action, error) {
|
||||
actions := make([]*action, 0)
|
||||
rawActions := util.SplitNoEmpty(s, ";")
|
||||
for _, rawAction := range rawActions {
|
||||
newAction := &action{
|
||||
Headers: make(map[string]string),
|
||||
Extras: make(map[string]string),
|
||||
}
|
||||
parts := util.SplitNoEmpty(rawAction, ",")
|
||||
if len(parts) < 3 {
|
||||
return nil, wrapErrHTTP(errHTTPBadRequestActionsInvalid, "action requires at least keys 'action', 'label' and one parameter: %s", rawAction)
|
||||
}
|
||||
for i, part := range parts {
|
||||
key, value := util.SplitKV(part, "=")
|
||||
if key == "" && i == 0 {
|
||||
newAction.Action = value
|
||||
} else if key == "" && i == 1 {
|
||||
newAction.Label = value
|
||||
} else if key == "" && util.InStringList([]string{"view", "http"}, newAction.Action) && i == 2 {
|
||||
newAction.URL = value
|
||||
} else if strings.HasPrefix(key, "headers.") {
|
||||
newAction.Headers[strings.TrimPrefix(key, "headers.")] = value
|
||||
} else if strings.HasPrefix(key, "extras.") {
|
||||
newAction.Extras[strings.TrimPrefix(key, "extras.")] = value
|
||||
} else if key != "" {
|
||||
switch strings.ToLower(key) {
|
||||
case "action":
|
||||
newAction.Action = value
|
||||
case "label":
|
||||
newAction.Label = value
|
||||
case "clear":
|
||||
lvalue := strings.ToLower(value)
|
||||
if !util.InStringList([]string{"true", "yes", "1", "false", "no", "0"}, lvalue) {
|
||||
return nil, wrapErrHTTP(errHTTPBadRequestActionsInvalid, "'clear=%s' not allowed", value)
|
||||
}
|
||||
newAction.Clear = lvalue == "true" || lvalue == "yes" || lvalue == "1"
|
||||
case "url":
|
||||
newAction.URL = value
|
||||
case "method":
|
||||
newAction.Method = value
|
||||
case "body":
|
||||
newAction.Body = value
|
||||
default:
|
||||
return nil, wrapErrHTTP(errHTTPBadRequestActionsInvalid, "key '%s' unknown", key)
|
||||
}
|
||||
} else {
|
||||
return nil, wrapErrHTTP(errHTTPBadRequestActionsInvalid, "unknown term '%s'", part)
|
||||
}
|
||||
}
|
||||
actions = append(actions, newAction)
|
||||
}
|
||||
return actions, nil
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue