| 
									
										
										
										
											2016-06-15 20:45:05 +08:00
										 |  |  | package notifications | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2016-06-16 14:15:48 +08:00
										 |  |  | 	"bytes" | 
					
						
							| 
									
										
										
										
											2016-10-03 15:38:03 +08:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2019-01-11 15:56:50 +08:00
										 |  |  | 	"crypto/tls" | 
					
						
							| 
									
										
										
										
											2016-07-27 18:09:55 +08:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2018-12-27 20:16:58 +08:00
										 |  |  | 	"io" | 
					
						
							| 
									
										
										
										
											2016-07-27 18:09:55 +08:00
										 |  |  | 	"io/ioutil" | 
					
						
							| 
									
										
										
										
											2017-02-25 00:22:12 +08:00
										 |  |  | 	"net" | 
					
						
							| 
									
										
										
										
											2016-06-15 20:45:05 +08:00
										 |  |  | 	"net/http" | 
					
						
							| 
									
										
										
										
											2017-02-25 00:22:12 +08:00
										 |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2016-06-15 20:45:05 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-03 15:38:03 +08:00
										 |  |  | 	"golang.org/x/net/context/ctxhttp" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-16 14:15:48 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/util" | 
					
						
							| 
									
										
										
										
											2016-06-15 20:45:05 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type Webhook struct { | 
					
						
							| 
									
										
										
										
											2017-03-24 04:53:54 +08:00
										 |  |  | 	Url         string | 
					
						
							|  |  |  | 	User        string | 
					
						
							|  |  |  | 	Password    string | 
					
						
							|  |  |  | 	Body        string | 
					
						
							|  |  |  | 	HttpMethod  string | 
					
						
							|  |  |  | 	HttpHeader  map[string]string | 
					
						
							|  |  |  | 	ContentType string | 
					
						
							| 
									
										
										
										
											2016-06-15 20:45:05 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-25 00:22:12 +08:00
										 |  |  | var netTransport = &http.Transport{ | 
					
						
							| 
									
										
										
										
											2019-01-11 15:56:50 +08:00
										 |  |  | 	TLSClientConfig: &tls.Config{ | 
					
						
							|  |  |  | 		Renegotiation: tls.RenegotiateFreelyAsClient, | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2017-03-02 20:57:28 +08:00
										 |  |  | 	Proxy: http.ProxyFromEnvironment, | 
					
						
							| 
									
										
										
										
											2017-02-25 00:22:12 +08:00
										 |  |  | 	Dial: (&net.Dialer{ | 
					
						
							| 
									
										
										
										
											2019-05-08 16:37:48 +08:00
										 |  |  | 		Timeout: 30 * time.Second, | 
					
						
							| 
									
										
										
										
											2017-02-25 00:22:12 +08:00
										 |  |  | 	}).Dial, | 
					
						
							|  |  |  | 	TLSHandshakeTimeout: 5 * time.Second, | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | var netClient = &http.Client{ | 
					
						
							|  |  |  | 	Timeout:   time.Second * 30, | 
					
						
							|  |  |  | 	Transport: netTransport, | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-27 19:01:32 +08:00
										 |  |  | func (ns *NotificationService) sendWebRequestSync(ctx context.Context, webhook *Webhook) error { | 
					
						
							| 
									
										
										
										
											2016-10-18 22:18:16 +08:00
										 |  |  | 	if webhook.HttpMethod == "" { | 
					
						
							|  |  |  | 		webhook.HttpMethod = http.MethodPost | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-01 02:57:48 +08:00
										 |  |  | 	ns.log.Debug("Sending webhook", "url", webhook.Url, "http method", webhook.HttpMethod) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-24 17:42:54 +08:00
										 |  |  | 	if webhook.HttpMethod != http.MethodPost && webhook.HttpMethod != http.MethodPut { | 
					
						
							|  |  |  | 		return fmt.Errorf("webhook only supports HTTP methods PUT or POST") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-18 22:18:16 +08:00
										 |  |  | 	request, err := http.NewRequest(webhook.HttpMethod, webhook.Url, bytes.NewReader([]byte(webhook.Body))) | 
					
						
							| 
									
										
										
										
											2016-06-15 20:45:05 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 04:53:54 +08:00
										 |  |  | 	if webhook.ContentType == "" { | 
					
						
							|  |  |  | 		webhook.ContentType = "application/json" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-14 22:13:01 +08:00
										 |  |  | 	request.Header.Set("Content-Type", webhook.ContentType) | 
					
						
							|  |  |  | 	request.Header.Set("User-Agent", "Grafana") | 
					
						
							| 
									
										
										
										
											2018-05-07 21:40:43 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-05 17:44:31 +08:00
										 |  |  | 	if webhook.User != "" && webhook.Password != "" { | 
					
						
							| 
									
										
										
										
											2020-12-14 22:13:01 +08:00
										 |  |  | 		request.Header.Set("Authorization", util.GetBasicAuthHeader(webhook.User, webhook.Password)) | 
					
						
							| 
									
										
										
										
											2016-12-05 17:44:31 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-19 16:29:40 +08:00
										 |  |  | 	for k, v := range webhook.HttpHeader { | 
					
						
							|  |  |  | 		request.Header.Set(k, v) | 
					
						
							| 
									
										
										
										
											2017-01-19 15:25:21 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-25 00:22:12 +08:00
										 |  |  | 	resp, err := ctxhttp.Do(ctx, netClient, request) | 
					
						
							| 
									
										
										
										
											2016-06-15 20:45:05 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-12-15 16:32:06 +08:00
										 |  |  | 	defer func() { | 
					
						
							|  |  |  | 		if err := resp.Body.Close(); err != nil { | 
					
						
							|  |  |  | 			ns.log.Warn("Failed to close response body", "err", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}() | 
					
						
							| 
									
										
										
										
											2018-12-27 20:16:58 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-03 15:38:03 +08:00
										 |  |  | 	if resp.StatusCode/100 == 2 { | 
					
						
							| 
									
										
										
										
											2020-06-27 02:47:06 +08:00
										 |  |  | 		ns.log.Debug("Webhook succeeded", "url", webhook.Url, "statuscode", resp.Status) | 
					
						
							| 
									
										
										
										
											2018-12-27 20:16:58 +08:00
										 |  |  | 		// flushing the body enables the transport to reuse the same connection
 | 
					
						
							| 
									
										
										
										
											2019-10-22 20:08:18 +08:00
										 |  |  | 		if _, err := io.Copy(ioutil.Discard, resp.Body); err != nil { | 
					
						
							|  |  |  | 			ns.log.Error("Failed to copy resp.Body to ioutil.Discard", "err", err) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-10-03 15:38:03 +08:00
										 |  |  | 		return nil | 
					
						
							| 
									
										
										
										
											2016-07-27 18:09:55 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-03 15:38:03 +08:00
										 |  |  | 	body, err := ioutil.ReadAll(resp.Body) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2016-07-27 18:09:55 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-10-03 15:38:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-27 02:47:06 +08:00
										 |  |  | 	ns.log.Debug("Webhook failed", "url", webhook.Url, "statuscode", resp.Status, "body", string(body)) | 
					
						
							| 
									
										
										
										
											2016-10-03 15:38:03 +08:00
										 |  |  | 	return fmt.Errorf("Webhook response status %v", resp.Status) | 
					
						
							| 
									
										
										
										
											2016-06-15 20:45:05 +08:00
										 |  |  | } |