mirror of
https://github.com/adnanh/webhook.git
synced 2025-05-15 10:04:44 +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
|
# 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.
|
[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?
|
# 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)).
|
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"
|
"crypto/sha1"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
@ -246,12 +247,49 @@ func (ha *Argument) Get(headers, query, payload *map[string]interface{}) (string
|
||||||
return "", false
|
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
|
// Hook type is a structure containing details for a single hook
|
||||||
type Hook struct {
|
type Hook struct {
|
||||||
ID string `json:"id,omitempty"`
|
ID string `json:"id,omitempty"`
|
||||||
ExecuteCommand string `json:"execute-command,omitempty"`
|
ExecuteCommand string `json:"execute-command,omitempty"`
|
||||||
CommandWorkingDirectory string `json:"command-working-directory,omitempty"`
|
CommandWorkingDirectory string `json:"command-working-directory,omitempty"`
|
||||||
ResponseMessage string `json:"response-message,omitempty"`
|
ResponseMessage string `json:"response-message,omitempty"`
|
||||||
|
ResponseHeaders ResponseHeaders `json:"response-headers,omitempty"`
|
||||||
CaptureCommandOutput bool `json:"include-command-output-in-response,omitempty"`
|
CaptureCommandOutput bool `json:"include-command-output-in-response,omitempty"`
|
||||||
PassEnvironmentToCommand []Argument `json:"pass-environment-to-command,omitempty"`
|
PassEnvironmentToCommand []Argument `json:"pass-environment-to-command,omitempty"`
|
||||||
PassArgumentsToCommand []Argument `json:"pass-arguments-to-command,omitempty"`
|
PassArgumentsToCommand []Argument `json:"pass-arguments-to-command,omitempty"`
|
||||||
|
|
|
@ -4,6 +4,13 @@
|
||||||
"execute-command": "/home/adnan/redeploy-go-webhook.sh",
|
"execute-command": "/home/adnan/redeploy-go-webhook.sh",
|
||||||
"command-working-directory": "/home/adnan/go",
|
"command-working-directory": "/home/adnan/go",
|
||||||
"response-message": "I got the payload!",
|
"response-message": "I got the payload!",
|
||||||
|
"response-headers":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "Access-Control-Allow-Origin",
|
||||||
|
"value": "*"
|
||||||
|
}
|
||||||
|
],
|
||||||
"pass-arguments-to-command":
|
"pass-arguments-to-command":
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
|
15
webhook.go
15
webhook.go
|
@ -21,7 +21,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
version = "2.3.7"
|
version = "2.3.8"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -36,6 +36,8 @@ var (
|
||||||
cert = flag.String("cert", "cert.pem", "path to the HTTPS certificate pem file")
|
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")
|
key = flag.String("key", "key.pem", "path to the HTTPS certificate private key pem file")
|
||||||
|
|
||||||
|
responseHeaders hook.ResponseHeaders
|
||||||
|
|
||||||
watcher *fsnotify.Watcher
|
watcher *fsnotify.Watcher
|
||||||
signals chan os.Signal
|
signals chan os.Signal
|
||||||
|
|
||||||
|
@ -45,6 +47,8 @@ var (
|
||||||
func main() {
|
func main() {
|
||||||
hooks = hook.Hooks{}
|
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()
|
flag.Parse()
|
||||||
|
|
||||||
log.SetPrefix("[webhook] ")
|
log.SetPrefix("[webhook] ")
|
||||||
|
@ -137,6 +141,10 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func hookHandler(w http.ResponseWriter, r *http.Request) {
|
func hookHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
for _, responseHeader := range responseHeaders {
|
||||||
|
w.Header().Set(responseHeader.Name, responseHeader.Value)
|
||||||
|
}
|
||||||
|
|
||||||
id := mux.Vars(r)["id"]
|
id := mux.Vars(r)["id"]
|
||||||
|
|
||||||
matchedHooks := hooks.MatchAll(id)
|
matchedHooks := hooks.MatchAll(id)
|
||||||
|
@ -180,6 +188,7 @@ func hookHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
// handle hook
|
// handle hook
|
||||||
for _, h := range matchedHooks {
|
for _, h := range matchedHooks {
|
||||||
|
|
||||||
err := h.ParseJSONParameters(&headers, &query, &payload)
|
err := h.ParseJSONParameters(&headers, &query, &payload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := fmt.Sprintf("error parsing JSON: %s", err)
|
msg := fmt.Sprintf("error parsing JSON: %s", err)
|
||||||
|
@ -207,6 +216,10 @@ func hookHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
if ok {
|
if ok {
|
||||||
log.Printf("%s hook triggered successfully\n", h.ID)
|
log.Printf("%s hook triggered successfully\n", h.ID)
|
||||||
|
|
||||||
|
for _, responseHeader := range h.ResponseHeaders {
|
||||||
|
w.Header().Set(responseHeader.Name, responseHeader.Value)
|
||||||
|
}
|
||||||
|
|
||||||
if h.CaptureCommandOutput {
|
if h.CaptureCommandOutput {
|
||||||
response := handleHook(h, &headers, &query, &payload, &body)
|
response := handleHook(h, &headers, &query, &payload, &body)
|
||||||
fmt.Fprintf(w, response)
|
fmt.Fprintf(w, response)
|
||||||
|
|
Loading…
Add table
Reference in a new issue