@@ -15,6 +15,8 @@ import (
1515 "github.com/benbjohnson/clock"
1616 "github.com/go-kit/log"
1717 "github.com/go-kit/log/level"
18+ "golang.org/x/oauth2"
19+
1820 commoncfg "github.com/prometheus/common/config"
1921
2022 "github.com/grafana/alerting/receivers"
@@ -23,19 +25,21 @@ import (
2325var ErrInvalidMethod = errors .New ("webhook only supports HTTP methods PUT or POST" )
2426
2527type clientConfiguration struct {
26- userAgent string
27- dialer net.Dialer // We use Dialer here instead of DialContext as our mqtt client doesn't support DialContext.
28- customDialer bool
28+ userAgent string
29+ dialer net.Dialer // We use Dialer here instead of DialContext as our mqtt client doesn't support DialContext.
30+ customDialer bool
31+ httpClientConfig HTTPClientConfig
2932}
3033
3134// defaultDialTimeout is the default timeout for the dialer, 30 seconds to match http.DefaultTransport.
3235const defaultDialTimeout = 30 * time .Second
3336
3437type Client struct {
35- cfg clientConfiguration
38+ cfg clientConfiguration
39+ oauth2TokenSource oauth2.TokenSource
3640}
3741
38- func NewClient (opts ... ClientOption ) * Client {
42+ func NewClient (opts ... ClientOption ) ( * Client , error ) {
3943 cfg := clientConfiguration {
4044 userAgent : "Grafana" ,
4145 dialer : net.Dialer {},
@@ -49,9 +53,25 @@ func NewClient(opts ...ClientOption) *Client {
4953 // Mostly defensive to ensure that timeout semantics don't change when given a custom dialer without a timeout.
5054 cfg .dialer .Timeout = defaultDialTimeout
5155 }
52- return & Client {
56+
57+ client := & Client {
5358 cfg : cfg ,
5459 }
60+
61+ if cfg .httpClientConfig .OAuth2 != nil {
62+ if err := ValidateOAuth2Config (cfg .httpClientConfig .OAuth2 ); err != nil {
63+ return nil , fmt .Errorf ("invalid OAuth2 configuration: %w" , err )
64+ }
65+ // If the user has provided an OAuth2 config, we need to prepare the OAuth2 token source. This needs to
66+ // be stored outside of the request so that the token expiration/re-use will work as expected.
67+ tokenSource , err := NewOAuth2TokenSource (cfg )
68+ if err != nil {
69+ return nil , err
70+ }
71+ client .oauth2TokenSource = tokenSource
72+ }
73+
74+ return client , nil
5575}
5676
5777type ClientOption func (* clientConfiguration )
@@ -69,6 +89,14 @@ func WithDialer(dialer net.Dialer) ClientOption {
6989 }
7090}
7191
92+ func WithHTTPClientConfig (config * HTTPClientConfig ) ClientOption {
93+ return func (c * clientConfiguration ) {
94+ if config != nil {
95+ c .httpClientConfig = * config
96+ }
97+ }
98+ }
99+
72100func ToHTTPClientOption (option ... ClientOption ) []commoncfg.HTTPClientOption {
73101 cfg := clientConfiguration {}
74102 for _ , opt := range option {
@@ -140,6 +168,11 @@ func (ns *Client) SendWebhook(ctx context.Context, l log.Logger, webhook *receiv
140168 }
141169 }
142170
171+ if ns .oauth2TokenSource != nil {
172+ level .Debug (l ).Log ("msg" , "Adding OAuth2 roundtripper to client" )
173+ client .Transport = NewOAuth2RoundTripper (ns .oauth2TokenSource , client .Transport )
174+ }
175+
143176 resp , err := client .Do (request )
144177 if err != nil {
145178 return redactURL (err )
0 commit comments