Add request source

Add "request" source with support for "method" and "remote-addr"
parameters.  Both values are taken from the raw http.Request object.

Fixes #312
This commit is contained in:
Cameron Moore 2020-11-20 16:32:55 -06:00
parent e513eb4bf4
commit 346c761ef6
6 changed files with 136 additions and 28 deletions

View file

@ -129,8 +129,24 @@ func TestWebhook(t *testing.T) {
t.Errorf("POST %q: failed to ready body: %s", tt.desc, err)
}
if res.StatusCode != tt.respStatus || string(body) != tt.respBody {
t.Errorf("failed %q (id: %s):\nexpected status: %#v, response: %s\ngot status: %#v, response: %s\ncommand output:\n%s\n", tt.desc, tt.id, tt.respStatus, tt.respBody, res.StatusCode, body, b)
// Test body
{
var bodyFailed bool
if res.StatusCode != tt.respStatus {
bodyFailed = true
}
if tt.bodyIsRE {
bodyFailed = string(body) == tt.respBody
} else {
r := regexp.MustCompile(tt.respBody)
bodyFailed = !r.Match(body)
}
if bodyFailed {
t.Errorf("failed %q (id: %s):\nexpected status: %#v, response: %s\ngot status: %#v, response: %s\ncommand output:\n%s\n", tt.desc, tt.id, tt.respStatus, tt.respBody, res.StatusCode, body, b)
}
}
if tt.logMatch == "" {
@ -303,6 +319,7 @@ var hookHandlerTests = []struct {
headers map[string]string
contentType string
body string
bodyIsRE bool
respStatus int
respBody string
@ -459,6 +476,7 @@ var hookHandlerTests = []struct {
"watchers":1
}
}`,
false,
http.StatusOK,
`arg: 1481a2de7b2a7d02428ad93446ab166be7793fbb lolwut@noway.biz
env: HOOK_head_commit.timestamp=2013-03-12T08:14:29-07:00
@ -473,6 +491,7 @@ env: HOOK_head_commit.timestamp=2013-03-12T08:14:29-07:00
nil,
"application/x-www-form-urlencoded",
`payload={"canon_url": "https://bitbucket.org","commits": [{"author": "marcus","branch": "master","files": [{"file": "somefile.py","type": "modified"}],"message": "Added some more things to somefile.py\n","node": "620ade18607a","parents": ["702c70160afc"],"raw_author": "Marcus Bertrand <marcus@somedomain.com>","raw_node": "620ade18607ac42d872b568bb92acaa9a28620e9","revision": null,"size": -1,"timestamp": "2012-05-30 05:58:56","utctimestamp": "2014-11-07 15:19:02+00:00"}],"repository": {"absolute_url": "/webhook/testing/","fork": false,"is_private": true,"name": "Project X","owner": "marcus","scm": "git","slug": "project-x","website": "https://atlassian.com/"},"user": "marcus"}`,
false,
http.StatusOK,
`success`,
``,
@ -526,6 +545,7 @@ env: HOOK_head_commit.timestamp=2013-03-12T08:14:29-07:00
],
"total_commits_count": 4
}`,
false,
http.StatusOK,
`arg: b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327 John Smith john@example.com
`,
@ -547,6 +567,7 @@ env: HOOK_head_commit.timestamp=2013-03-12T08:14:29-07:00
<message id="1" from_user="1" to_user="2">Hello!!</message>
</messages>
</app>`,
false,
http.StatusOK,
`success`,
``,
@ -569,6 +590,7 @@ env: HOOK_head_commit.timestamp=2013-03-12T08:14:29-07:00
"sg_message_id": "sg_message_id"
}
]`,
false,
http.StatusOK,
`success`,
``,
@ -601,6 +623,7 @@ Content-Transfer-Encoding: binary
binary data
--xxx--`,
false,
http.StatusOK,
`success`,
``,
@ -614,6 +637,7 @@ binary data
nil,
"application/json",
`{"exists": 1}`,
false,
http.StatusOK,
`success`,
``,
@ -627,6 +651,7 @@ binary data
nil,
"application/json",
`{"exists": 1}`,
false,
http.StatusOK,
`Hook rules were not satisfied.`,
`parameter node not found`,
@ -668,6 +693,7 @@ binary data
},
"ref":"refs/heads/master"
}`,
false,
http.StatusOK,
`arg: 1481a2de7b2a7d02428ad93446ab166be7793fbb lolwut@noway.biz
env: HOOK_head_commit.timestamp=2013-03-12T08:14:29-07:00
@ -710,6 +736,7 @@ env: HOOK_head_commit.timestamp=2013-03-12T08:14:29-07:00
},
"ref":"refs/heads/master"
}`,
false,
http.StatusOK,
`arg: 1481a2de7b2a7d02428ad93446ab166be7793fbb lolwut@noway.biz
`,
@ -724,34 +751,50 @@ env: HOOK_head_commit.timestamp=2013-03-12T08:14:29-07:00
map[string]string{"X-Hub-Signature": "33f9d709782f62b8b4a0178586c65ab098a39fe2"},
"application/json",
``,
false,
http.StatusOK,
``,
``,
},
{
"request-source",
"request-source",
nil,
"POST",
map[string]string{"X-Hub-Signature": "33f9d709782f62b8b4a0178586c65ab098a39fe2"},
"application/json",
`{}`,
true,
http.StatusOK,
`arg: POST 127.0.0.1:.*
`,
``,
},
// test with disallowed global HTTP method
{"global disallowed method", "bitbucket", []string{"Post "}, "GET", nil, `{}`, "application/json", http.StatusMethodNotAllowed, ``, ``},
{"global disallowed method", "bitbucket", []string{"Post "}, "GET", nil, `{}`, "application/json", false, http.StatusMethodNotAllowed, ``, ``},
// test with disallowed HTTP method
{"disallowed method", "github", nil, "Get", nil, `{}`, "application/json", http.StatusMethodNotAllowed, ``, ``},
{"disallowed method", "github", nil, "Get", nil, `{}`, "application/json", false, http.StatusMethodNotAllowed, ``, ``},
// test with custom return code
{"empty payload", "github", nil, "POST", nil, "application/json", `{}`, http.StatusBadRequest, `Hook rules were not satisfied.`, ``},
{"empty payload", "github", nil, "POST", nil, "application/json", `{}`, false, http.StatusBadRequest, `Hook rules were not satisfied.`, ``},
// test with custom invalid http code, should default to 200 OK
{"empty payload", "bitbucket", nil, "POST", nil, "application/json", `{}`, http.StatusOK, `Hook rules were not satisfied.`, ``},
{"empty payload", "bitbucket", nil, "POST", nil, "application/json", `{}`, false, http.StatusOK, `Hook rules were not satisfied.`, ``},
// test with no configured http return code, should default to 200 OK
{"empty payload", "gitlab", nil, "POST", nil, "application/json", `{}`, http.StatusOK, `Hook rules were not satisfied.`, ``},
{"empty payload", "gitlab", nil, "POST", nil, "application/json", `{}`, false, http.StatusOK, `Hook rules were not satisfied.`, ``},
// test capturing command output
{"don't capture output on success by default", "capture-command-output-on-success-not-by-default", nil, "POST", nil, "application/json", `{}`, http.StatusOK, ``, ``},
{"capture output on success with flag set", "capture-command-output-on-success-yes-with-flag", nil, "POST", nil, "application/json", `{}`, http.StatusOK, `arg: exit=0
{"don't capture output on success by default", "capture-command-output-on-success-not-by-default", nil, "POST", nil, "application/json", `{}`, false, http.StatusOK, ``, ``},
{"capture output on success with flag set", "capture-command-output-on-success-yes-with-flag", nil, "POST", nil, "application/json", `{}`, false, http.StatusOK, `arg: exit=0
`, ``},
{"don't capture output on error by default", "capture-command-output-on-error-not-by-default", nil, "POST", nil, "application/json", `{}`, http.StatusInternalServerError, `Error occurred while executing the hook's command. Please check your logs for more details.`, ``},
{"capture output on error with extra flag set", "capture-command-output-on-error-yes-with-extra-flag", nil, "POST", nil, "application/json", `{}`, http.StatusInternalServerError, `arg: exit=1
{"don't capture output on error by default", "capture-command-output-on-error-not-by-default", nil, "POST", nil, "application/json", `{}`, false, http.StatusInternalServerError, `Error occurred while executing the hook's command. Please check your logs for more details.`, ``},
{"capture output on error with extra flag set", "capture-command-output-on-error-yes-with-extra-flag", nil, "POST", nil, "application/json", `{}`, false, http.StatusInternalServerError, `arg: exit=1
`, ``},
// Check logs
{"static params should pass", "static-params-ok", nil, "POST", nil, "application/json", `{}`, http.StatusOK, "arg: passed\n", `(?s)command output: arg: passed`},
{"command with space logs warning", "warn-on-space", nil, "POST", nil, "application/json", `{}`, http.StatusInternalServerError, "Error occurred while executing the hook's command. Please check your logs for more details.", `(?s)error in exec:.*use 'pass[-]arguments[-]to[-]command' to specify args`},
{"unsupported content type error", "github", nil, "POST", map[string]string{"Content-Type": "nonexistent/format"}, "application/json", `{}`, http.StatusBadRequest, `Hook rules were not satisfied.`, `(?s)error parsing body payload due to unsupported content type header:`},
{"static params should pass", "static-params-ok", nil, "POST", nil, "application/json", `{}`, false, http.StatusOK, "arg: passed\n", `(?s)command output: arg: passed`},
{"command with space logs warning", "warn-on-space", nil, "POST", nil, "application/json", `{}`, false, http.StatusInternalServerError, "Error occurred while executing the hook's command. Please check your logs for more details.", `(?s)error in exec:.*use 'pass[-]arguments[-]to[-]command' to specify args`},
{"unsupported content type error", "github", nil, "POST", map[string]string{"Content-Type": "nonexistent/format"}, "application/json", `{}`, false, http.StatusBadRequest, `Hook rules were not satisfied.`, `(?s)error parsing body payload due to unsupported content type header:`},
}
// buffer provides a concurrency-safe bytes.Buffer to tests above.