mirror of
https://github.com/ncarlier/webhookd.git
synced 2025-04-12 16:43:42 +00:00

- No external dependencies - No predefined directory structure - Able to launch any kind of shell script with custom parameters - Get script output as text event stream (SSE) - Using common Makefiles - Extends docker/dind Docker image
140 lines
3.2 KiB
Go
140 lines
3.2 KiB
Go
package notification
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"mime/multipart"
|
|
"net/http"
|
|
"net/textproto"
|
|
"net/url"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
// HTTPNotifier is able to send a notification to a HTTP endpoint.
|
|
type HTTPNotifier struct {
|
|
URL string
|
|
From string
|
|
To string
|
|
User []string
|
|
}
|
|
|
|
func newHTTPNotifier() *HTTPNotifier {
|
|
notifier := new(HTTPNotifier)
|
|
notifier.URL = os.Getenv("APP_HTTP_NOTIFIER_URL")
|
|
if notifier.URL == "" {
|
|
log.Println("Unable to create HTTP notifier. APP_HTTP_NOTIFIER_URL not set.")
|
|
return nil
|
|
}
|
|
user := os.Getenv("APP_HTTP_NOTIFIER_USER")
|
|
if user != "" {
|
|
notifier.User = strings.Split(user, ":")
|
|
}
|
|
notifier.From = os.Getenv("APP_NOTIFIER_FROM")
|
|
if notifier.From == "" {
|
|
notifier.From = "webhookd <noreply@nunux.org>"
|
|
}
|
|
notifier.To = os.Getenv("APP_NOTIFIER_TO")
|
|
if notifier.To == "" {
|
|
notifier.To = "hostmaster@nunux.org"
|
|
}
|
|
return notifier
|
|
}
|
|
|
|
// Notify send a notification to a HTTP endpoint.
|
|
func (n *HTTPNotifier) Notify(subject string, text string, attachfile string) {
|
|
log.Println("Sending notification '" + subject + "' to " + n.URL + " ...")
|
|
data := make(url.Values)
|
|
data.Set("from", n.From)
|
|
data.Set("to", n.To)
|
|
data.Set("subject", subject)
|
|
data.Set("text", text)
|
|
|
|
if attachfile != "" {
|
|
file, err := os.Open(attachfile)
|
|
if err != nil {
|
|
log.Println(err)
|
|
return
|
|
}
|
|
defer file.Close()
|
|
|
|
body := &bytes.Buffer{}
|
|
writer := multipart.NewWriter(body)
|
|
|
|
mh := make(textproto.MIMEHeader)
|
|
mh.Set("Content-Type", "application/x-gzip")
|
|
mh.Set("Content-Disposition", fmt.Sprintf("form-data; name=\"attachment\"; filename=\"%s\"", filepath.Base(attachfile)))
|
|
part, err := writer.CreatePart(mh)
|
|
if err != nil {
|
|
log.Println("Unable to create for file", err)
|
|
return
|
|
}
|
|
_, err = io.Copy(part, file)
|
|
|
|
for key, val := range data {
|
|
_ = writer.WriteField(key, val[0])
|
|
}
|
|
|
|
err = writer.Close()
|
|
if err != nil {
|
|
log.Println("Unable to close the gzip writer", err)
|
|
return
|
|
}
|
|
req, err := http.NewRequest("POST", n.URL, body)
|
|
if err != nil {
|
|
log.Println("Unable to post request", err)
|
|
}
|
|
defer req.Body.Close()
|
|
req.Header.Set("Content-Type", writer.FormDataContentType())
|
|
|
|
if len(n.User) == 2 {
|
|
req.SetBasicAuth(n.User[0], n.User[1])
|
|
}
|
|
|
|
// Submit the request
|
|
client := &http.Client{}
|
|
res, err := client.Do(req)
|
|
if err != nil {
|
|
log.Println("Unable to do the request", err)
|
|
return
|
|
}
|
|
|
|
// Check the response
|
|
if res.StatusCode != http.StatusOK {
|
|
log.Println("bad status: ", res.Status)
|
|
log.Println(res.Body)
|
|
return
|
|
}
|
|
log.Println("HTTP notification sended with attachment: ", attachfile)
|
|
} else {
|
|
req, err := http.NewRequest("POST", n.URL, bytes.NewBufferString(data.Encode()))
|
|
if err != nil {
|
|
log.Println("Unable to post request", err)
|
|
}
|
|
defer req.Body.Close()
|
|
|
|
if len(n.User) == 2 {
|
|
req.SetBasicAuth(n.User[0], n.User[1])
|
|
}
|
|
|
|
// Submit the request
|
|
client := &http.Client{}
|
|
res, err := client.Do(req)
|
|
if err != nil {
|
|
log.Println("Unable to do the request", err)
|
|
return
|
|
}
|
|
|
|
// Check the response
|
|
if res.StatusCode != http.StatusOK {
|
|
log.Println("bad status: ", res.Status)
|
|
log.Println(res.Body)
|
|
return
|
|
}
|
|
log.Println("HTTP notification sended.")
|
|
}
|
|
}
|