mirror of
https://github.com/yusing/godoxy.git
synced 2025-06-01 09:32:35 +02:00
rules: updated help message, make values optional, fixes tests
This commit is contained in:
parent
bcf2dde091
commit
43ed860e18
6 changed files with 130 additions and 47 deletions
|
@ -2,19 +2,19 @@ package http
|
||||||
|
|
||||||
import "net/http"
|
import "net/http"
|
||||||
|
|
||||||
var validMethods = map[string]struct{}{
|
|
||||||
http.MethodGet: {},
|
|
||||||
http.MethodHead: {},
|
|
||||||
http.MethodPost: {},
|
|
||||||
http.MethodPut: {},
|
|
||||||
http.MethodPatch: {},
|
|
||||||
http.MethodDelete: {},
|
|
||||||
http.MethodConnect: {},
|
|
||||||
http.MethodOptions: {},
|
|
||||||
http.MethodTrace: {},
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsMethodValid(method string) bool {
|
func IsMethodValid(method string) bool {
|
||||||
_, ok := validMethods[method]
|
switch method {
|
||||||
return ok
|
case http.MethodGet,
|
||||||
|
http.MethodHead,
|
||||||
|
http.MethodPost,
|
||||||
|
http.MethodPut,
|
||||||
|
http.MethodPatch,
|
||||||
|
http.MethodDelete,
|
||||||
|
http.MethodConnect,
|
||||||
|
http.MethodOptions,
|
||||||
|
http.MethodTrace:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,8 @@ var (
|
||||||
ErrInvalidCommandSequence = E.New("invalid command sequence")
|
ErrInvalidCommandSequence = E.New("invalid command sequence")
|
||||||
ErrInvalidSetTarget = E.New("invalid `rule.set` target")
|
ErrInvalidSetTarget = E.New("invalid `rule.set` target")
|
||||||
|
|
||||||
ErrExpectNoArg = ErrInvalidArguments.Withf("expect no arg")
|
ErrExpectNoArg = E.New("expect no arg")
|
||||||
ErrExpectOneArg = ErrInvalidArguments.Withf("expect 1 arg")
|
ErrExpectOneArg = E.New("expect 1 arg")
|
||||||
ErrExpectTwoArgs = ErrInvalidArguments.Withf("expect 2 args")
|
ErrExpectTwoArgs = E.New("expect 2 args")
|
||||||
|
ErrExpectKVOptionalV = E.New("expect 'key' or 'key value'")
|
||||||
)
|
)
|
||||||
|
|
|
@ -20,9 +20,8 @@ func (h *Help) String() string {
|
||||||
sb.WriteString(h.command)
|
sb.WriteString(h.command)
|
||||||
sb.WriteString(" ")
|
sb.WriteString(" ")
|
||||||
for arg := range h.args {
|
for arg := range h.args {
|
||||||
sb.WriteRune('<')
|
sb.WriteString(strings.ToUpper(arg))
|
||||||
sb.WriteString(arg)
|
sb.WriteRune(' ')
|
||||||
sb.WriteString("> ")
|
|
||||||
}
|
}
|
||||||
if h.description != "" {
|
if h.description != "" {
|
||||||
sb.WriteString("\n\t")
|
sb.WriteString("\n\t")
|
||||||
|
@ -32,7 +31,7 @@ func (h *Help) String() string {
|
||||||
sb.WriteRune('\n')
|
sb.WriteRune('\n')
|
||||||
for arg, desc := range h.args {
|
for arg, desc := range h.args {
|
||||||
sb.WriteRune('\t')
|
sb.WriteRune('\t')
|
||||||
sb.WriteString(arg)
|
sb.WriteString(strings.ToUpper(arg))
|
||||||
sb.WriteString(": ")
|
sb.WriteString(": ")
|
||||||
sb.WriteString(desc)
|
sb.WriteString(desc)
|
||||||
sb.WriteRune('\n')
|
sb.WriteRune('\n')
|
||||||
|
|
|
@ -34,15 +34,25 @@ var checkers = map[string]struct {
|
||||||
help: Help{
|
help: Help{
|
||||||
command: OnHeader,
|
command: OnHeader,
|
||||||
args: map[string]string{
|
args: map[string]string{
|
||||||
"key": "the header key",
|
"key": "the header key",
|
||||||
"value": "the header value",
|
"[value]": "the header value",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
validate: toStrTuple,
|
validate: toKVOptionalV,
|
||||||
builder: func(args any) CheckFunc {
|
builder: func(args any) CheckFunc {
|
||||||
k, v := args.(*StrTuple).Unpack()
|
k, v := args.(*StrTuple).Unpack()
|
||||||
|
if v == "" {
|
||||||
|
return func(cached Cache, r *http.Request) bool {
|
||||||
|
return len(r.Header[k]) > 0
|
||||||
|
}
|
||||||
|
}
|
||||||
return func(cached Cache, r *http.Request) bool {
|
return func(cached Cache, r *http.Request) bool {
|
||||||
return r.Header.Get(k) == v
|
for _, vv := range r.Header[k] {
|
||||||
|
if v == vv {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -50,13 +60,18 @@ var checkers = map[string]struct {
|
||||||
help: Help{
|
help: Help{
|
||||||
command: OnQuery,
|
command: OnQuery,
|
||||||
args: map[string]string{
|
args: map[string]string{
|
||||||
"key": "the query key",
|
"key": "the query key",
|
||||||
"value": "the query value",
|
"[value]": "the query value",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
validate: toStrTuple,
|
validate: toKVOptionalV,
|
||||||
builder: func(args any) CheckFunc {
|
builder: func(args any) CheckFunc {
|
||||||
k, v := args.(*StrTuple).Unpack()
|
k, v := args.(*StrTuple).Unpack()
|
||||||
|
if v == "" {
|
||||||
|
return func(cached Cache, r *http.Request) bool {
|
||||||
|
return len(cached.GetQueries(r)[k]) > 0
|
||||||
|
}
|
||||||
|
}
|
||||||
return func(cached Cache, r *http.Request) bool {
|
return func(cached Cache, r *http.Request) bool {
|
||||||
queries := cached.GetQueries(r)[k]
|
queries := cached.GetQueries(r)[k]
|
||||||
for _, query := range queries {
|
for _, query := range queries {
|
||||||
|
@ -72,13 +87,24 @@ var checkers = map[string]struct {
|
||||||
help: Help{
|
help: Help{
|
||||||
command: OnCookie,
|
command: OnCookie,
|
||||||
args: map[string]string{
|
args: map[string]string{
|
||||||
"key": "the cookie key",
|
"key": "the cookie key",
|
||||||
"value": "the cookie value",
|
"[value]": "the cookie value",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
validate: toStrTuple,
|
validate: toKVOptionalV,
|
||||||
builder: func(args any) CheckFunc {
|
builder: func(args any) CheckFunc {
|
||||||
k, v := args.(*StrTuple).Unpack()
|
k, v := args.(*StrTuple).Unpack()
|
||||||
|
if v == "" {
|
||||||
|
return func(cached Cache, r *http.Request) bool {
|
||||||
|
cookies := cached.GetCookies(r)
|
||||||
|
for _, cookie := range cookies {
|
||||||
|
if cookie.Name == k {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
return func(cached Cache, r *http.Request) bool {
|
return func(cached Cache, r *http.Request) bool {
|
||||||
cookies := cached.GetCookies(r)
|
cookies := cached.GetCookies(r)
|
||||||
for _, cookie := range cookies {
|
for _, cookie := range cookies {
|
||||||
|
@ -95,13 +121,18 @@ var checkers = map[string]struct {
|
||||||
help: Help{
|
help: Help{
|
||||||
command: OnForm,
|
command: OnForm,
|
||||||
args: map[string]string{
|
args: map[string]string{
|
||||||
"key": "the form key",
|
"key": "the form key",
|
||||||
"value": "the form value",
|
"[value]": "the form value",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
validate: toStrTuple,
|
validate: toKVOptionalV,
|
||||||
builder: func(args any) CheckFunc {
|
builder: func(args any) CheckFunc {
|
||||||
k, v := args.(*StrTuple).Unpack()
|
k, v := args.(*StrTuple).Unpack()
|
||||||
|
if v == "" {
|
||||||
|
return func(cached Cache, r *http.Request) bool {
|
||||||
|
return r.FormValue(k) != ""
|
||||||
|
}
|
||||||
|
}
|
||||||
return func(cached Cache, r *http.Request) bool {
|
return func(cached Cache, r *http.Request) bool {
|
||||||
return r.FormValue(k) == v
|
return r.FormValue(k) == v
|
||||||
}
|
}
|
||||||
|
@ -111,13 +142,18 @@ var checkers = map[string]struct {
|
||||||
help: Help{
|
help: Help{
|
||||||
command: OnPostForm,
|
command: OnPostForm,
|
||||||
args: map[string]string{
|
args: map[string]string{
|
||||||
"key": "the form key",
|
"key": "the form key",
|
||||||
"value": "the form value",
|
"[value]": "the form value",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
validate: toStrTuple,
|
validate: toKVOptionalV,
|
||||||
builder: func(args any) CheckFunc {
|
builder: func(args any) CheckFunc {
|
||||||
k, v := args.(*StrTuple).Unpack()
|
k, v := args.(*StrTuple).Unpack()
|
||||||
|
if v == "" {
|
||||||
|
return func(cached Cache, r *http.Request) bool {
|
||||||
|
return r.PostFormValue(k) != ""
|
||||||
|
}
|
||||||
|
}
|
||||||
return func(cached Cache, r *http.Request) bool {
|
return func(cached Cache, r *http.Request) bool {
|
||||||
return r.PostFormValue(k) == v
|
return r.PostFormValue(k) == v
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,25 +15,50 @@ func TestParseOn(t *testing.T) {
|
||||||
}{
|
}{
|
||||||
// header
|
// header
|
||||||
{
|
{
|
||||||
name: "header_valid",
|
name: "header_valid_kv",
|
||||||
input: "header Connection Upgrade",
|
input: "header Connection Upgrade",
|
||||||
wantErr: nil,
|
wantErr: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "header_invalid",
|
name: "header_valid_k",
|
||||||
input: "header Connection",
|
input: "header Connection",
|
||||||
wantErr: ErrInvalidArguments,
|
wantErr: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "header_missing_arg",
|
||||||
|
input: "header",
|
||||||
|
wantErr: ErrExpectKVOptionalV,
|
||||||
},
|
},
|
||||||
// query
|
// query
|
||||||
{
|
{
|
||||||
name: "query_valid",
|
name: "query_valid_kv",
|
||||||
input: "query key value",
|
input: "query key value",
|
||||||
wantErr: nil,
|
wantErr: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "query_invalid",
|
name: "query_valid_k",
|
||||||
input: "query key",
|
input: "query key",
|
||||||
wantErr: ErrInvalidArguments,
|
wantErr: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "query_missing_arg",
|
||||||
|
input: "query",
|
||||||
|
wantErr: ErrExpectKVOptionalV,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "cookie_valid_kv",
|
||||||
|
input: "cookie key value",
|
||||||
|
wantErr: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "cookie_valid_k",
|
||||||
|
input: "cookie key",
|
||||||
|
wantErr: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "cookie_missing_arg",
|
||||||
|
input: "cookie",
|
||||||
|
wantErr: ErrExpectKVOptionalV,
|
||||||
},
|
},
|
||||||
// method
|
// method
|
||||||
{
|
{
|
||||||
|
@ -43,9 +68,14 @@ func TestParseOn(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "method_invalid",
|
name: "method_invalid",
|
||||||
input: "method",
|
input: "method invalid",
|
||||||
wantErr: ErrInvalidArguments,
|
wantErr: ErrInvalidArguments,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "method_missing_arg",
|
||||||
|
input: "method",
|
||||||
|
wantErr: ErrExpectOneArg,
|
||||||
|
},
|
||||||
// path
|
// path
|
||||||
{
|
{
|
||||||
name: "path_valid",
|
name: "path_valid",
|
||||||
|
@ -53,9 +83,9 @@ func TestParseOn(t *testing.T) {
|
||||||
wantErr: nil,
|
wantErr: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "path_invalid",
|
name: "path_missing_arg",
|
||||||
input: "path",
|
input: "path",
|
||||||
wantErr: ErrInvalidArguments,
|
wantErr: ErrExpectOneArg,
|
||||||
},
|
},
|
||||||
// remote
|
// remote
|
||||||
{
|
{
|
||||||
|
@ -65,9 +95,14 @@ func TestParseOn(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "remote_invalid",
|
name: "remote_invalid",
|
||||||
input: "remote",
|
input: "remote abcd",
|
||||||
wantErr: ErrInvalidArguments,
|
wantErr: ErrInvalidArguments,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "remote_missing_arg",
|
||||||
|
input: "remote",
|
||||||
|
wantErr: ErrExpectOneArg,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "unknown_target",
|
name: "unknown_target",
|
||||||
input: "unknown",
|
input: "unknown",
|
||||||
|
|
|
@ -36,6 +36,18 @@ func toStrTuple(args []string) (any, E.Error) {
|
||||||
return &StrTuple{args[0], args[1]}, nil
|
return &StrTuple{args[0], args[1]}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// toKVOptionalV returns *StrTuple that value is optional.
|
||||||
|
func toKVOptionalV(args []string) (any, E.Error) {
|
||||||
|
switch len(args) {
|
||||||
|
case 1:
|
||||||
|
return &StrTuple{args[0], ""}, nil
|
||||||
|
case 2:
|
||||||
|
return &StrTuple{args[0], args[1]}, nil
|
||||||
|
default:
|
||||||
|
return nil, ErrExpectKVOptionalV
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// validateURL returns types.URL with the URL validated.
|
// validateURL returns types.URL with the URL validated.
|
||||||
func validateURL(args []string) (any, E.Error) {
|
func validateURL(args []string) (any, E.Error) {
|
||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
|
|
Loading…
Add table
Reference in a new issue