mirror of
https://github.com/adnanh/webhook.git
synced 2025-05-14 17:44:42 +00:00
commit
ec42679305
4 changed files with 72 additions and 11 deletions
|
@ -59,6 +59,9 @@ However, hook defined like that could pose a security threat to your system, bec
|
|||
# Using HTTPS
|
||||
[webhook](https://github.com/adnanh/webhook/) by default serves hooks using http. If you want [webhook](https://github.com/adnanh/webhook/) to serve secure content using https, you can use the `-secure` flag while starting [webhook](https://github.com/adnanh/webhook/). Files containing a certificate and matching private key for the server must be provided using the `-cert /path/to/cert.pem` and `-key /path/to/key.pem` flags. If the certificate is signed by a certificate authority, the cert file should be the concatenation of the server's certificate followed by the CA's certificate.
|
||||
|
||||
# CORS Headers
|
||||
If you want to set CORS headers, you can use the `-header name=value` flag while starting [webhook](https://github.com/adnanh/webhook/) to set the appropriate CORS headers that will be returned with each response.
|
||||
|
||||
# Interested in running webhook inside of a Docker container?
|
||||
You can use [almir/webhook](https://hub.docker.com/r/almir/webhook/) docker image, or create your own (please read [this discussion](https://github.com/adnanh/webhook/issues/63)).
|
||||
|
||||
|
|
38
hook/hook.go
38
hook/hook.go
|
@ -5,6 +5,7 @@ import (
|
|||
"crypto/sha1"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"reflect"
|
||||
|
@ -246,12 +247,49 @@ func (ha *Argument) Get(headers, query, payload *map[string]interface{}) (string
|
|||
return "", false
|
||||
}
|
||||
|
||||
// Header is a structure containing header name and it's value
|
||||
type Header struct {
|
||||
Name string `json:"name"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
// ResponseHeaders is a slice of Header objects
|
||||
type ResponseHeaders []Header
|
||||
|
||||
func (h *ResponseHeaders) String() string {
|
||||
// a 'hack' to display name=value in flag usage listing
|
||||
if len(*h) == 0 {
|
||||
return "name=value"
|
||||
}
|
||||
|
||||
result := make([]string, len(*h))
|
||||
|
||||
for idx, responseHeader := range *h {
|
||||
result[idx] = fmt.Sprintf("%s=%s", responseHeader.Name, responseHeader.Value)
|
||||
}
|
||||
|
||||
return fmt.Sprint(strings.Join(result, ", "))
|
||||
}
|
||||
|
||||
// Set method appends new Header object from header=value notation
|
||||
func (h *ResponseHeaders) Set(value string) error {
|
||||
splitResult := strings.SplitN(value, "=", 2)
|
||||
|
||||
if len(splitResult) != 2 {
|
||||
return errors.New("header flag must be in name=value format")
|
||||
}
|
||||
|
||||
*h = append(*h, Header{Name: splitResult[0], Value: splitResult[1]})
|
||||
return nil
|
||||
}
|
||||
|
||||
// Hook type is a structure containing details for a single hook
|
||||
type Hook struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
ExecuteCommand string `json:"execute-command,omitempty"`
|
||||
CommandWorkingDirectory string `json:"command-working-directory,omitempty"`
|
||||
ResponseMessage string `json:"response-message,omitempty"`
|
||||
ResponseHeaders ResponseHeaders `json:"response-headers,omitempty"`
|
||||
CaptureCommandOutput bool `json:"include-command-output-in-response,omitempty"`
|
||||
PassEnvironmentToCommand []Argument `json:"pass-environment-to-command,omitempty"`
|
||||
PassArgumentsToCommand []Argument `json:"pass-arguments-to-command,omitempty"`
|
||||
|
|
|
@ -4,6 +4,13 @@
|
|||
"execute-command": "/home/adnan/redeploy-go-webhook.sh",
|
||||
"command-working-directory": "/home/adnan/go",
|
||||
"response-message": "I got the payload!",
|
||||
"response-headers":
|
||||
[
|
||||
{
|
||||
"name": "Access-Control-Allow-Origin",
|
||||
"value": "*"
|
||||
}
|
||||
],
|
||||
"pass-arguments-to-command":
|
||||
[
|
||||
{
|
||||
|
|
15
webhook.go
15
webhook.go
|
@ -21,7 +21,7 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
version = "2.3.7"
|
||||
version = "2.3.8"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -36,6 +36,8 @@ var (
|
|||
cert = flag.String("cert", "cert.pem", "path to the HTTPS certificate pem file")
|
||||
key = flag.String("key", "key.pem", "path to the HTTPS certificate private key pem file")
|
||||
|
||||
responseHeaders hook.ResponseHeaders
|
||||
|
||||
watcher *fsnotify.Watcher
|
||||
signals chan os.Signal
|
||||
|
||||
|
@ -45,6 +47,8 @@ var (
|
|||
func main() {
|
||||
hooks = hook.Hooks{}
|
||||
|
||||
flag.Var(&responseHeaders, "header", "response header to return, specified in format name=value, use multiple times to set multiple headers")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
log.SetPrefix("[webhook] ")
|
||||
|
@ -137,6 +141,10 @@ func main() {
|
|||
}
|
||||
|
||||
func hookHandler(w http.ResponseWriter, r *http.Request) {
|
||||
for _, responseHeader := range responseHeaders {
|
||||
w.Header().Set(responseHeader.Name, responseHeader.Value)
|
||||
}
|
||||
|
||||
id := mux.Vars(r)["id"]
|
||||
|
||||
matchedHooks := hooks.MatchAll(id)
|
||||
|
@ -180,6 +188,7 @@ func hookHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// handle hook
|
||||
for _, h := range matchedHooks {
|
||||
|
||||
err := h.ParseJSONParameters(&headers, &query, &payload)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("error parsing JSON: %s", err)
|
||||
|
@ -207,6 +216,10 @@ func hookHandler(w http.ResponseWriter, r *http.Request) {
|
|||
if ok {
|
||||
log.Printf("%s hook triggered successfully\n", h.ID)
|
||||
|
||||
for _, responseHeader := range h.ResponseHeaders {
|
||||
w.Header().Set(responseHeader.Name, responseHeader.Value)
|
||||
}
|
||||
|
||||
if h.CaptureCommandOutput {
|
||||
response := handleHook(h, &headers, &query, &payload, &body)
|
||||
fmt.Fprintf(w, response)
|
||||
|
|
Loading…
Add table
Reference in a new issue