mirror of
https://github.com/adnanh/webhook.git
synced 2025-05-14 17:44:42 +00:00
feat: an Argument type that evaluates a template against the Request
Added a new "source": "template" argument type, that evaluates a Go text/template against a context containing the request Body, Query, Payload and Headers, enabling much richer mapping from request attributes to argument parameters.
This commit is contained in:
parent
9f725b2cb0
commit
9892bc678b
2 changed files with 138 additions and 63 deletions
|
@ -41,6 +41,7 @@ const (
|
||||||
SourceEntirePayload string = "entire-payload"
|
SourceEntirePayload string = "entire-payload"
|
||||||
SourceEntireQuery string = "entire-query"
|
SourceEntireQuery string = "entire-query"
|
||||||
SourceEntireHeaders string = "entire-headers"
|
SourceEntireHeaders string = "entire-headers"
|
||||||
|
SourceTemplate string = "template"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -438,6 +439,76 @@ type Argument struct {
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
EnvName string `json:"envname,omitempty"`
|
EnvName string `json:"envname,omitempty"`
|
||||||
Base64Decode bool `json:"base64decode,omitempty"`
|
Base64Decode bool `json:"base64decode,omitempty"`
|
||||||
|
|
||||||
|
// if the Argument is SourceTemplate, this will be the compiled template,
|
||||||
|
// otherwise it will be nil
|
||||||
|
template *template.Template
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON parses an Argument in the normal way, and then allows the
|
||||||
|
// newly-loaded Argument to do any necessary post-processing.
|
||||||
|
func (ha *Argument) UnmarshalJSON(text []byte) error {
|
||||||
|
// First unmarshal as normal, skipping the custom unmarshaller
|
||||||
|
type jsonArgument Argument
|
||||||
|
if err := json.Unmarshal(text, (*jsonArgument)(ha)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return ha.postProcess()
|
||||||
|
}
|
||||||
|
|
||||||
|
// postProcess does the necessary post-unmarshal processing for this argument.
|
||||||
|
// If the argument is a SourceTemplate it compiles the template string into an
|
||||||
|
// executable template. This method is idempotent, i.e. it is safe to call
|
||||||
|
// more than once on the same Argument
|
||||||
|
func (ha *Argument) postProcess() error {
|
||||||
|
if ha.Source == SourceTemplate && ha.template == nil {
|
||||||
|
// now compile the template
|
||||||
|
var err error
|
||||||
|
ha.template, err = template.New("argument").Option("missingkey=zero").Parse(ha.Name)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// templateContext is the context passed as "." to the template executed when
|
||||||
|
// getting an Argument of type SourceTemplate
|
||||||
|
type templateContext struct {
|
||||||
|
ID string
|
||||||
|
ContentType string
|
||||||
|
Body []byte
|
||||||
|
Headers map[string]interface{}
|
||||||
|
Query map[string]interface{}
|
||||||
|
Payload map[string]interface{}
|
||||||
|
Method string
|
||||||
|
RemoteAddr string
|
||||||
|
}
|
||||||
|
|
||||||
|
// BodyText is a convenience to access the request Body as a string. This means
|
||||||
|
// you can just say {{ .BodyText }} instead of having to do a trick like
|
||||||
|
// {{ printf "%s" .Body }}
|
||||||
|
func (ctx *templateContext) BodyText() string {
|
||||||
|
return string(ctx.Body)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetHeader is a function to fetch a specific item out of the headers map
|
||||||
|
// by its case insensitive name. The header name is converted to canonical form
|
||||||
|
// before being looked up in the header map, e.g. {{ .GetHeader "x-request-id" }}
|
||||||
|
func (ctx *templateContext) GetHeader(name string) interface{} {
|
||||||
|
return ctx.Headers[textproto.CanonicalMIMEHeaderKey(name)]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ha *Argument) runTemplate(r *Request) (string, error) {
|
||||||
|
w := &strings.Builder{}
|
||||||
|
ctx := &templateContext{
|
||||||
|
r.ID, r.ContentType, r.Body, r.Headers, r.Query, r.Payload, r.RawRequest.Method, r.RawRequest.RemoteAddr,
|
||||||
|
}
|
||||||
|
err := ha.template.Execute(w, ctx)
|
||||||
|
if err == nil {
|
||||||
|
return w.String(), nil
|
||||||
|
}
|
||||||
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get Argument method returns the value for the Argument's key name
|
// Get Argument method returns the value for the Argument's key name
|
||||||
|
@ -500,6 +571,9 @@ func (ha *Argument) Get(r *Request) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return string(res), nil
|
return string(res), nil
|
||||||
|
|
||||||
|
case SourceTemplate:
|
||||||
|
return ha.runTemplate(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
if source != nil {
|
if source != nil {
|
||||||
|
|
|
@ -274,7 +274,7 @@ var argumentGetTests = []struct {
|
||||||
|
|
||||||
func TestArgumentGet(t *testing.T) {
|
func TestArgumentGet(t *testing.T) {
|
||||||
for _, tt := range argumentGetTests {
|
for _, tt := range argumentGetTests {
|
||||||
a := Argument{tt.source, tt.name, "", false}
|
a := Argument{tt.source, tt.name, "", false, nil}
|
||||||
r := &Request{
|
r := &Request{
|
||||||
Headers: tt.headers,
|
Headers: tt.headers,
|
||||||
Query: tt.query,
|
Query: tt.query,
|
||||||
|
@ -294,14 +294,14 @@ var hookParseJSONParametersTests = []struct {
|
||||||
rheaders, rquery, rpayload map[string]interface{}
|
rheaders, rquery, rpayload map[string]interface{}
|
||||||
ok bool
|
ok bool
|
||||||
}{
|
}{
|
||||||
{[]Argument{Argument{"header", "a", "", false}}, map[string]interface{}{"A": `{"b": "y"}`}, nil, nil, map[string]interface{}{"A": map[string]interface{}{"b": "y"}}, nil, nil, true},
|
{[]Argument{Argument{"header", "a", "", false, nil}}, map[string]interface{}{"A": `{"b": "y"}`}, nil, nil, map[string]interface{}{"A": map[string]interface{}{"b": "y"}}, nil, nil, true},
|
||||||
{[]Argument{Argument{"url", "a", "", false}}, nil, map[string]interface{}{"a": `{"b": "y"}`}, nil, nil, map[string]interface{}{"a": map[string]interface{}{"b": "y"}}, nil, true},
|
{[]Argument{Argument{"url", "a", "", false, nil}}, nil, map[string]interface{}{"a": `{"b": "y"}`}, nil, nil, map[string]interface{}{"a": map[string]interface{}{"b": "y"}}, nil, true},
|
||||||
{[]Argument{Argument{"payload", "a", "", false}}, nil, nil, map[string]interface{}{"a": `{"b": "y"}`}, nil, nil, map[string]interface{}{"a": map[string]interface{}{"b": "y"}}, true},
|
{[]Argument{Argument{"payload", "a", "", false, nil}}, nil, nil, map[string]interface{}{"a": `{"b": "y"}`}, nil, nil, map[string]interface{}{"a": map[string]interface{}{"b": "y"}}, true},
|
||||||
{[]Argument{Argument{"header", "z", "", false}}, map[string]interface{}{"Z": `{}`}, nil, nil, map[string]interface{}{"Z": map[string]interface{}{}}, nil, nil, true},
|
{[]Argument{Argument{"header", "z", "", false, nil}}, map[string]interface{}{"Z": `{}`}, nil, nil, map[string]interface{}{"Z": map[string]interface{}{}}, nil, nil, true},
|
||||||
// failures
|
// failures
|
||||||
{[]Argument{Argument{"header", "z", "", false}}, map[string]interface{}{"Z": ``}, nil, nil, map[string]interface{}{"Z": ``}, nil, nil, false}, // empty string
|
{[]Argument{Argument{"header", "z", "", false, nil}}, map[string]interface{}{"Z": ``}, nil, nil, map[string]interface{}{"Z": ``}, nil, nil, false}, // empty string
|
||||||
{[]Argument{Argument{"header", "y", "", false}}, map[string]interface{}{"X": `{}`}, nil, nil, map[string]interface{}{"X": `{}`}, nil, nil, false}, // missing parameter
|
{[]Argument{Argument{"header", "y", "", false, nil}}, map[string]interface{}{"X": `{}`}, nil, nil, map[string]interface{}{"X": `{}`}, nil, nil, false}, // missing parameter
|
||||||
{[]Argument{Argument{"string", "z", "", false}}, map[string]interface{}{"Z": ``}, nil, nil, map[string]interface{}{"Z": ``}, nil, nil, false}, // invalid argument source
|
{[]Argument{Argument{"string", "z", "", false, nil}}, map[string]interface{}{"Z": ``}, nil, nil, map[string]interface{}{"Z": ``}, nil, nil, false}, // invalid argument source
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHookParseJSONParameters(t *testing.T) {
|
func TestHookParseJSONParameters(t *testing.T) {
|
||||||
|
@ -326,9 +326,9 @@ var hookExtractCommandArgumentsTests = []struct {
|
||||||
value []string
|
value []string
|
||||||
ok bool
|
ok bool
|
||||||
}{
|
}{
|
||||||
{"test", []Argument{Argument{"header", "a", "", false}}, map[string]interface{}{"A": "z"}, nil, nil, []string{"test", "z"}, true},
|
{"test", []Argument{Argument{"header", "a", "", false, nil}}, map[string]interface{}{"A": "z"}, nil, nil, []string{"test", "z"}, true},
|
||||||
// failures
|
// failures
|
||||||
{"fail", []Argument{Argument{"payload", "a", "", false}}, map[string]interface{}{"A": "z"}, nil, nil, []string{"fail", ""}, false},
|
{"fail", []Argument{Argument{"payload", "a", "", false, nil}}, map[string]interface{}{"A": "z"}, nil, nil, []string{"fail", ""}, false},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHookExtractCommandArguments(t *testing.T) {
|
func TestHookExtractCommandArguments(t *testing.T) {
|
||||||
|
@ -351,20 +351,21 @@ func TestHookExtractCommandArguments(t *testing.T) {
|
||||||
// we test both cases where the name of the data is used as the name of the
|
// we test both cases where the name of the data is used as the name of the
|
||||||
// env key & the case where the hook definition sets the env var name to a
|
// env key & the case where the hook definition sets the env var name to a
|
||||||
// fixed value using the envname construct like so::
|
// fixed value using the envname construct like so::
|
||||||
// [
|
//
|
||||||
// {
|
// [
|
||||||
// "id": "push",
|
// {
|
||||||
// "execute-command": "bb2mm",
|
// "id": "push",
|
||||||
// "command-working-directory": "/tmp",
|
// "execute-command": "bb2mm",
|
||||||
// "pass-environment-to-command":
|
// "command-working-directory": "/tmp",
|
||||||
// [
|
// "pass-environment-to-command":
|
||||||
// {
|
// [
|
||||||
// "source": "entire-payload",
|
// {
|
||||||
// "envname": "PAYLOAD"
|
// "source": "entire-payload",
|
||||||
// },
|
// "envname": "PAYLOAD"
|
||||||
// ]
|
// },
|
||||||
// }
|
// ]
|
||||||
// ]
|
// }
|
||||||
|
// ]
|
||||||
var hookExtractCommandArgumentsForEnvTests = []struct {
|
var hookExtractCommandArgumentsForEnvTests = []struct {
|
||||||
exec string
|
exec string
|
||||||
args []Argument
|
args []Argument
|
||||||
|
@ -375,14 +376,14 @@ var hookExtractCommandArgumentsForEnvTests = []struct {
|
||||||
// successes
|
// successes
|
||||||
{
|
{
|
||||||
"test",
|
"test",
|
||||||
[]Argument{Argument{"header", "a", "", false}},
|
[]Argument{Argument{"header", "a", "", false, nil}},
|
||||||
map[string]interface{}{"A": "z"}, nil, nil,
|
map[string]interface{}{"A": "z"}, nil, nil,
|
||||||
[]string{"HOOK_a=z"},
|
[]string{"HOOK_a=z"},
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"test",
|
"test",
|
||||||
[]Argument{Argument{"header", "a", "MYKEY", false}},
|
[]Argument{Argument{"header", "a", "MYKEY", false, nil}},
|
||||||
map[string]interface{}{"A": "z"}, nil, nil,
|
map[string]interface{}{"A": "z"}, nil, nil,
|
||||||
[]string{"MYKEY=z"},
|
[]string{"MYKEY=z"},
|
||||||
true,
|
true,
|
||||||
|
@ -390,7 +391,7 @@ var hookExtractCommandArgumentsForEnvTests = []struct {
|
||||||
// failures
|
// failures
|
||||||
{
|
{
|
||||||
"fail",
|
"fail",
|
||||||
[]Argument{Argument{"payload", "a", "", false}},
|
[]Argument{Argument{"payload", "a", "", false, nil}},
|
||||||
map[string]interface{}{"A": "z"}, nil, nil,
|
map[string]interface{}{"A": "z"}, nil, nil,
|
||||||
[]string{},
|
[]string{},
|
||||||
false,
|
false,
|
||||||
|
@ -489,24 +490,24 @@ var matchRuleTests = []struct {
|
||||||
ok bool
|
ok bool
|
||||||
err bool
|
err bool
|
||||||
}{
|
}{
|
||||||
{"value", "", "", "z", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": "z"}, nil, nil, []byte{}, "", true, false},
|
{"value", "", "", "z", "", Argument{"header", "a", "", false, nil}, map[string]interface{}{"A": "z"}, nil, nil, []byte{}, "", true, false},
|
||||||
{"regex", "^z", "", "z", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": "z"}, nil, nil, []byte{}, "", true, false},
|
{"regex", "^z", "", "z", "", Argument{"header", "a", "", false, nil}, map[string]interface{}{"A": "z"}, nil, nil, []byte{}, "", true, false},
|
||||||
{"payload-hmac-sha1", "", "secret", "", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": "b17e04cbb22afa8ffbff8796fc1894ed27badd9e"}, nil, nil, []byte(`{"a": "z"}`), "", true, false},
|
{"payload-hmac-sha1", "", "secret", "", "", Argument{"header", "a", "", false, nil}, map[string]interface{}{"A": "b17e04cbb22afa8ffbff8796fc1894ed27badd9e"}, nil, nil, []byte(`{"a": "z"}`), "", true, false},
|
||||||
{"payload-hash-sha1", "", "secret", "", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": "b17e04cbb22afa8ffbff8796fc1894ed27badd9e"}, nil, nil, []byte(`{"a": "z"}`), "", true, false},
|
{"payload-hash-sha1", "", "secret", "", "", Argument{"header", "a", "", false, nil}, map[string]interface{}{"A": "b17e04cbb22afa8ffbff8796fc1894ed27badd9e"}, nil, nil, []byte(`{"a": "z"}`), "", true, false},
|
||||||
{"payload-hmac-sha256", "", "secret", "", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": "f417af3a21bd70379b5796d5f013915e7029f62c580fb0f500f59a35a6f04c89"}, nil, nil, []byte(`{"a": "z"}`), "", true, false},
|
{"payload-hmac-sha256", "", "secret", "", "", Argument{"header", "a", "", false, nil}, map[string]interface{}{"A": "f417af3a21bd70379b5796d5f013915e7029f62c580fb0f500f59a35a6f04c89"}, nil, nil, []byte(`{"a": "z"}`), "", true, false},
|
||||||
{"payload-hash-sha256", "", "secret", "", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": "f417af3a21bd70379b5796d5f013915e7029f62c580fb0f500f59a35a6f04c89"}, nil, nil, []byte(`{"a": "z"}`), "", true, false},
|
{"payload-hash-sha256", "", "secret", "", "", Argument{"header", "a", "", false, nil}, map[string]interface{}{"A": "f417af3a21bd70379b5796d5f013915e7029f62c580fb0f500f59a35a6f04c89"}, nil, nil, []byte(`{"a": "z"}`), "", true, false},
|
||||||
// failures
|
// failures
|
||||||
{"value", "", "", "X", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": "z"}, nil, nil, []byte{}, "", false, false},
|
{"value", "", "", "X", "", Argument{"header", "a", "", false, nil}, map[string]interface{}{"A": "z"}, nil, nil, []byte{}, "", false, false},
|
||||||
{"regex", "^X", "", "", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": "z"}, nil, nil, []byte{}, "", false, false},
|
{"regex", "^X", "", "", "", Argument{"header", "a", "", false, nil}, map[string]interface{}{"A": "z"}, nil, nil, []byte{}, "", false, false},
|
||||||
{"value", "", "2", "X", "", Argument{"header", "a", "", false}, map[string]interface{}{"Y": "z"}, nil, nil, []byte{}, "", false, true}, // reference invalid header
|
{"value", "", "2", "X", "", Argument{"header", "a", "", false, nil}, map[string]interface{}{"Y": "z"}, nil, nil, []byte{}, "", false, true}, // reference invalid header
|
||||||
// errors
|
// errors
|
||||||
{"regex", "*", "", "", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": "z"}, nil, nil, []byte{}, "", false, true}, // invalid regex
|
{"regex", "*", "", "", "", Argument{"header", "a", "", false, nil}, map[string]interface{}{"A": "z"}, nil, nil, []byte{}, "", false, true}, // invalid regex
|
||||||
{"payload-hmac-sha1", "", "secret", "", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": ""}, nil, nil, []byte{}, "", false, true}, // invalid hmac
|
{"payload-hmac-sha1", "", "secret", "", "", Argument{"header", "a", "", false, nil}, map[string]interface{}{"A": ""}, nil, nil, []byte{}, "", false, true}, // invalid hmac
|
||||||
{"payload-hash-sha1", "", "secret", "", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": ""}, nil, nil, []byte{}, "", false, true}, // invalid hmac
|
{"payload-hash-sha1", "", "secret", "", "", Argument{"header", "a", "", false, nil}, map[string]interface{}{"A": ""}, nil, nil, []byte{}, "", false, true}, // invalid hmac
|
||||||
{"payload-hmac-sha256", "", "secret", "", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": ""}, nil, nil, []byte{}, "", false, true}, // invalid hmac
|
{"payload-hmac-sha256", "", "secret", "", "", Argument{"header", "a", "", false, nil}, map[string]interface{}{"A": ""}, nil, nil, []byte{}, "", false, true}, // invalid hmac
|
||||||
{"payload-hash-sha256", "", "secret", "", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": ""}, nil, nil, []byte{}, "", false, true}, // invalid hmac
|
{"payload-hash-sha256", "", "secret", "", "", Argument{"header", "a", "", false, nil}, map[string]interface{}{"A": ""}, nil, nil, []byte{}, "", false, true}, // invalid hmac
|
||||||
{"payload-hmac-sha512", "", "secret", "", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": ""}, nil, nil, []byte{}, "", false, true}, // invalid hmac
|
{"payload-hmac-sha512", "", "secret", "", "", Argument{"header", "a", "", false, nil}, map[string]interface{}{"A": ""}, nil, nil, []byte{}, "", false, true}, // invalid hmac
|
||||||
{"payload-hash-sha512", "", "secret", "", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": ""}, nil, nil, []byte{}, "", false, true}, // invalid hmac
|
{"payload-hash-sha512", "", "secret", "", "", Argument{"header", "a", "", false, nil}, map[string]interface{}{"A": ""}, nil, nil, []byte{}, "", false, true}, // invalid hmac
|
||||||
// IP whitelisting, valid cases
|
// IP whitelisting, valid cases
|
||||||
{"ip-whitelist", "", "", "", "192.168.0.1/24", Argument{}, nil, nil, nil, []byte{}, "192.168.0.2:9000", true, false}, // valid IPv4, with range
|
{"ip-whitelist", "", "", "", "192.168.0.1/24", Argument{}, nil, nil, nil, []byte{}, "192.168.0.2:9000", true, false}, // valid IPv4, with range
|
||||||
{"ip-whitelist", "", "", "", "192.168.0.1/24", Argument{}, nil, nil, nil, []byte{}, "192.168.0.2:9000", true, false}, // valid IPv4, with range
|
{"ip-whitelist", "", "", "", "192.168.0.1/24", Argument{}, nil, nil, nil, []byte{}, "192.168.0.2:9000", true, false}, // valid IPv4, with range
|
||||||
|
@ -552,8 +553,8 @@ var andRuleTests = []struct {
|
||||||
{
|
{
|
||||||
"(a=z, b=y): a=z && b=y",
|
"(a=z, b=y): a=z && b=y",
|
||||||
AndRule{
|
AndRule{
|
||||||
{Match: &MatchRule{"value", "", "", "z", Argument{"header", "a", "", false}, ""}},
|
{Match: &MatchRule{"value", "", "", "z", Argument{"header", "a", "", false, nil}, ""}},
|
||||||
{Match: &MatchRule{"value", "", "", "y", Argument{"header", "b", "", false}, ""}},
|
{Match: &MatchRule{"value", "", "", "y", Argument{"header", "b", "", false, nil}, ""}},
|
||||||
},
|
},
|
||||||
map[string]interface{}{"A": "z", "B": "y"}, nil, nil,
|
map[string]interface{}{"A": "z", "B": "y"}, nil, nil,
|
||||||
[]byte{},
|
[]byte{},
|
||||||
|
@ -562,8 +563,8 @@ var andRuleTests = []struct {
|
||||||
{
|
{
|
||||||
"(a=z, b=Y): a=z && b=y",
|
"(a=z, b=Y): a=z && b=y",
|
||||||
AndRule{
|
AndRule{
|
||||||
{Match: &MatchRule{"value", "", "", "z", Argument{"header", "a", "", false}, ""}},
|
{Match: &MatchRule{"value", "", "", "z", Argument{"header", "a", "", false, nil}, ""}},
|
||||||
{Match: &MatchRule{"value", "", "", "y", Argument{"header", "b", "", false}, ""}},
|
{Match: &MatchRule{"value", "", "", "y", Argument{"header", "b", "", false, nil}, ""}},
|
||||||
},
|
},
|
||||||
map[string]interface{}{"A": "z", "B": "Y"}, nil, nil,
|
map[string]interface{}{"A": "z", "B": "Y"}, nil, nil,
|
||||||
[]byte{},
|
[]byte{},
|
||||||
|
@ -573,22 +574,22 @@ var andRuleTests = []struct {
|
||||||
{
|
{
|
||||||
"(a=z, b=y, c=x, d=w=, e=X, f=X): a=z && (b=y && c=x) && (d=w || e=v) && !f=u",
|
"(a=z, b=y, c=x, d=w=, e=X, f=X): a=z && (b=y && c=x) && (d=w || e=v) && !f=u",
|
||||||
AndRule{
|
AndRule{
|
||||||
{Match: &MatchRule{"value", "", "", "z", Argument{"header", "a", "", false}, ""}},
|
{Match: &MatchRule{"value", "", "", "z", Argument{"header", "a", "", false, nil}, ""}},
|
||||||
{
|
{
|
||||||
And: &AndRule{
|
And: &AndRule{
|
||||||
{Match: &MatchRule{"value", "", "", "y", Argument{"header", "b", "", false}, ""}},
|
{Match: &MatchRule{"value", "", "", "y", Argument{"header", "b", "", false, nil}, ""}},
|
||||||
{Match: &MatchRule{"value", "", "", "x", Argument{"header", "c", "", false}, ""}},
|
{Match: &MatchRule{"value", "", "", "x", Argument{"header", "c", "", false, nil}, ""}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Or: &OrRule{
|
Or: &OrRule{
|
||||||
{Match: &MatchRule{"value", "", "", "w", Argument{"header", "d", "", false}, ""}},
|
{Match: &MatchRule{"value", "", "", "w", Argument{"header", "d", "", false, nil}, ""}},
|
||||||
{Match: &MatchRule{"value", "", "", "v", Argument{"header", "e", "", false}, ""}},
|
{Match: &MatchRule{"value", "", "", "v", Argument{"header", "e", "", false, nil}, ""}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Not: &NotRule{
|
Not: &NotRule{
|
||||||
Match: &MatchRule{"value", "", "", "u", Argument{"header", "f", "", false}, ""},
|
Match: &MatchRule{"value", "", "", "u", Argument{"header", "f", "", false, nil}, ""},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -600,7 +601,7 @@ var andRuleTests = []struct {
|
||||||
// failures
|
// failures
|
||||||
{
|
{
|
||||||
"invalid rule",
|
"invalid rule",
|
||||||
AndRule{{Match: &MatchRule{"value", "", "", "X", Argument{"header", "a", "", false}, ""}}},
|
AndRule{{Match: &MatchRule{"value", "", "", "X", Argument{"header", "a", "", false, nil}, ""}}},
|
||||||
map[string]interface{}{"Y": "z"}, nil, nil, nil,
|
map[string]interface{}{"Y": "z"}, nil, nil, nil,
|
||||||
false, true,
|
false, true,
|
||||||
},
|
},
|
||||||
|
@ -632,8 +633,8 @@ var orRuleTests = []struct {
|
||||||
{
|
{
|
||||||
"(a=z, b=X): a=z || b=y",
|
"(a=z, b=X): a=z || b=y",
|
||||||
OrRule{
|
OrRule{
|
||||||
{Match: &MatchRule{"value", "", "", "z", Argument{"header", "a", "", false}, ""}},
|
{Match: &MatchRule{"value", "", "", "z", Argument{"header", "a", "", false, nil}, ""}},
|
||||||
{Match: &MatchRule{"value", "", "", "y", Argument{"header", "b", "", false}, ""}},
|
{Match: &MatchRule{"value", "", "", "y", Argument{"header", "b", "", false, nil}, ""}},
|
||||||
},
|
},
|
||||||
map[string]interface{}{"A": "z", "B": "X"}, nil, nil,
|
map[string]interface{}{"A": "z", "B": "X"}, nil, nil,
|
||||||
[]byte{},
|
[]byte{},
|
||||||
|
@ -642,8 +643,8 @@ var orRuleTests = []struct {
|
||||||
{
|
{
|
||||||
"(a=X, b=y): a=z || b=y",
|
"(a=X, b=y): a=z || b=y",
|
||||||
OrRule{
|
OrRule{
|
||||||
{Match: &MatchRule{"value", "", "", "z", Argument{"header", "a", "", false}, ""}},
|
{Match: &MatchRule{"value", "", "", "z", Argument{"header", "a", "", false, nil}, ""}},
|
||||||
{Match: &MatchRule{"value", "", "", "y", Argument{"header", "b", "", false}, ""}},
|
{Match: &MatchRule{"value", "", "", "y", Argument{"header", "b", "", false, nil}, ""}},
|
||||||
},
|
},
|
||||||
map[string]interface{}{"A": "X", "B": "y"}, nil, nil,
|
map[string]interface{}{"A": "X", "B": "y"}, nil, nil,
|
||||||
[]byte{},
|
[]byte{},
|
||||||
|
@ -652,8 +653,8 @@ var orRuleTests = []struct {
|
||||||
{
|
{
|
||||||
"(a=Z, b=Y): a=z || b=y",
|
"(a=Z, b=Y): a=z || b=y",
|
||||||
OrRule{
|
OrRule{
|
||||||
{Match: &MatchRule{"value", "", "", "z", Argument{"header", "a", "", false}, ""}},
|
{Match: &MatchRule{"value", "", "", "z", Argument{"header", "a", "", false, nil}, ""}},
|
||||||
{Match: &MatchRule{"value", "", "", "y", Argument{"header", "b", "", false}, ""}},
|
{Match: &MatchRule{"value", "", "", "y", Argument{"header", "b", "", false, nil}, ""}},
|
||||||
},
|
},
|
||||||
map[string]interface{}{"A": "Z", "B": "Y"}, nil, nil,
|
map[string]interface{}{"A": "Z", "B": "Y"}, nil, nil,
|
||||||
[]byte{},
|
[]byte{},
|
||||||
|
@ -663,7 +664,7 @@ var orRuleTests = []struct {
|
||||||
{
|
{
|
||||||
"missing parameter node",
|
"missing parameter node",
|
||||||
OrRule{
|
OrRule{
|
||||||
{Match: &MatchRule{"value", "", "", "z", Argument{"header", "a", "", false}, ""}},
|
{Match: &MatchRule{"value", "", "", "z", Argument{"header", "a", "", false, nil}, ""}},
|
||||||
},
|
},
|
||||||
map[string]interface{}{"Y": "Z"}, nil, nil,
|
map[string]interface{}{"Y": "Z"}, nil, nil,
|
||||||
[]byte{},
|
[]byte{},
|
||||||
|
@ -694,8 +695,8 @@ var notRuleTests = []struct {
|
||||||
ok bool
|
ok bool
|
||||||
err bool
|
err bool
|
||||||
}{
|
}{
|
||||||
{"(a=z): !a=X", NotRule{Match: &MatchRule{"value", "", "", "X", Argument{"header", "a", "", false}, ""}}, map[string]interface{}{"A": "z"}, nil, nil, []byte{}, true, false},
|
{"(a=z): !a=X", NotRule{Match: &MatchRule{"value", "", "", "X", Argument{"header", "a", "", false, nil}, ""}}, map[string]interface{}{"A": "z"}, nil, nil, []byte{}, true, false},
|
||||||
{"(a=z): !a=z", NotRule{Match: &MatchRule{"value", "", "", "z", Argument{"header", "a", "", false}, ""}}, map[string]interface{}{"A": "z"}, nil, nil, []byte{}, false, false},
|
{"(a=z): !a=z", NotRule{Match: &MatchRule{"value", "", "", "z", Argument{"header", "a", "", false, nil}, ""}}, map[string]interface{}{"A": "z"}, nil, nil, []byte{}, false, false},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNotRule(t *testing.T) {
|
func TestNotRule(t *testing.T) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue