mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Datasource: Add custom headers on alerting queries (#19508)
* Add custom headers on alerting queries Reference issue #15381 Signed-off-by: Martin Schneppenheim <martin.schneppenheim@rewe-digital.com> * Fix datasource transport tests * Migrate decrypting header test to models pkg * Check correct header * Add HTTP transport test Fixes #15381
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"sync"
|
||||
@@ -17,10 +18,25 @@ type proxyTransportCache struct {
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// dataSourceTransport implements http.RoundTripper (https://golang.org/pkg/net/http/#RoundTripper)
|
||||
type dataSourceTransport struct {
|
||||
headers map[string]string
|
||||
transport *http.Transport
|
||||
}
|
||||
|
||||
// RoundTrip executes a single HTTP transaction, returning a Response for the provided Request.
|
||||
func (d *dataSourceTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
for key, value := range d.headers {
|
||||
req.Header.Set(key, value)
|
||||
}
|
||||
|
||||
return d.transport.RoundTrip(req)
|
||||
}
|
||||
|
||||
type cachedTransport struct {
|
||||
updated time.Time
|
||||
|
||||
*http.Transport
|
||||
*dataSourceTransport
|
||||
}
|
||||
|
||||
var ptc = proxyTransportCache{
|
||||
@@ -40,12 +56,12 @@ func (ds *DataSource) GetHttpClient() (*http.Client, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (ds *DataSource) GetHttpTransport() (*http.Transport, error) {
|
||||
func (ds *DataSource) GetHttpTransport() (*dataSourceTransport, error) {
|
||||
ptc.Lock()
|
||||
defer ptc.Unlock()
|
||||
|
||||
if t, present := ptc.cache[ds.Id]; present && ds.Updated.Equal(t.updated) {
|
||||
return t.Transport, nil
|
||||
return t.dataSourceTransport, nil
|
||||
}
|
||||
|
||||
tlsConfig, err := ds.GetTLSConfig()
|
||||
@@ -55,6 +71,8 @@ func (ds *DataSource) GetHttpTransport() (*http.Transport, error) {
|
||||
|
||||
tlsConfig.Renegotiation = tls.RenegotiateFreelyAsClient
|
||||
|
||||
// Create transport which adds all
|
||||
customHeaders := ds.getCustomHeaders()
|
||||
transport := &http.Transport{
|
||||
TLSClientConfig: tlsConfig,
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
@@ -68,12 +86,17 @@ func (ds *DataSource) GetHttpTransport() (*http.Transport, error) {
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
}
|
||||
|
||||
ptc.cache[ds.Id] = cachedTransport{
|
||||
Transport: transport,
|
||||
updated: ds.Updated,
|
||||
dsTransport := &dataSourceTransport{
|
||||
headers: customHeaders,
|
||||
transport: transport,
|
||||
}
|
||||
|
||||
return transport, nil
|
||||
ptc.cache[ds.Id] = cachedTransport{
|
||||
dataSourceTransport: dsTransport,
|
||||
updated: ds.Updated,
|
||||
}
|
||||
|
||||
return dsTransport, nil
|
||||
}
|
||||
|
||||
func (ds *DataSource) GetTLSConfig() (*tls.Config, error) {
|
||||
@@ -110,3 +133,32 @@ func (ds *DataSource) GetTLSConfig() (*tls.Config, error) {
|
||||
|
||||
return tlsConfig, nil
|
||||
}
|
||||
|
||||
// getCustomHeaders returns a map with all the to be set headers
|
||||
// The map key represents the HeaderName and the value represents this header's value
|
||||
func (ds *DataSource) getCustomHeaders() map[string]string {
|
||||
headers := make(map[string]string)
|
||||
if ds.JsonData == nil {
|
||||
return headers
|
||||
}
|
||||
|
||||
decrypted := ds.SecureJsonData.Decrypt()
|
||||
index := 1
|
||||
for {
|
||||
headerNameSuffix := fmt.Sprintf("httpHeaderName%d", index)
|
||||
headerValueSuffix := fmt.Sprintf("httpHeaderValue%d", index)
|
||||
|
||||
key := ds.JsonData.Get(headerNameSuffix).MustString()
|
||||
if key == "" {
|
||||
// No (more) header values are available
|
||||
break
|
||||
}
|
||||
|
||||
if val, ok := decrypted[headerValueSuffix]; ok {
|
||||
headers[key] = val
|
||||
}
|
||||
index++
|
||||
}
|
||||
|
||||
return headers
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user