1 package adal
2 3 // Copyright 2017 Microsoft Corporation
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 17 import (
18 "crypto/tls"
19 "net"
20 "net/http"
21 "net/http/cookiejar"
22 "sync"
23 "time"
24 25 "github.com/Azure/go-autorest/tracing"
26 )
27 28 const (
29 contentType = "Content-Type"
30 mimeTypeFormPost = "application/x-www-form-urlencoded"
31 )
32 33 // DO NOT ACCESS THIS DIRECTLY. go through sender()
34 var defaultSender Sender
35 var defaultSenderInit = &sync.Once{}
36 37 // Sender is the interface that wraps the Do method to send HTTP requests.
38 //
39 // The standard http.Client conforms to this interface.
40 type Sender interface {
41 Do(*http.Request) (*http.Response, error)
42 }
43 44 // SenderFunc is a method that implements the Sender interface.
45 type SenderFunc func(*http.Request) (*http.Response, error)
46 47 // Do implements the Sender interface on SenderFunc.
48 func (sf SenderFunc) Do(r *http.Request) (*http.Response, error) {
49 return sf(r)
50 }
51 52 // SendDecorator takes and possibly decorates, by wrapping, a Sender. Decorators may affect the
53 // http.Request and pass it along or, first, pass the http.Request along then react to the
54 // http.Response result.
55 type SendDecorator func(Sender) Sender
56 57 // CreateSender creates, decorates, and returns, as a Sender, the default http.Client.
58 func CreateSender(decorators ...SendDecorator) Sender {
59 return DecorateSender(sender(), decorators...)
60 }
61 62 // DecorateSender accepts a Sender and a, possibly empty, set of SendDecorators, which is applies to
63 // the Sender. Decorators are applied in the order received, but their affect upon the request
64 // depends on whether they are a pre-decorator (change the http.Request and then pass it along) or a
65 // post-decorator (pass the http.Request along and react to the results in http.Response).
66 func DecorateSender(s Sender, decorators ...SendDecorator) Sender {
67 for _, decorate := range decorators {
68 s = decorate(s)
69 }
70 return s
71 }
72 73 func sender() Sender {
74 // note that we can't init defaultSender in init() since it will
75 // execute before calling code has had a chance to enable tracing
76 defaultSenderInit.Do(func() {
77 // copied from http.DefaultTransport with a TLS minimum version.
78 transport := &http.Transport{
79 Proxy: http.ProxyFromEnvironment,
80 DialContext: (&net.Dialer{
81 Timeout: 30 * time.Second,
82 KeepAlive: 30 * time.Second,
83 }).DialContext,
84 ForceAttemptHTTP2: true,
85 MaxIdleConns: 100,
86 IdleConnTimeout: 90 * time.Second,
87 TLSHandshakeTimeout: 10 * time.Second,
88 ExpectContinueTimeout: 1 * time.Second,
89 TLSClientConfig: &tls.Config{
90 MinVersion: tls.VersionTLS12,
91 },
92 }
93 var roundTripper http.RoundTripper = transport
94 if tracing.IsEnabled() {
95 roundTripper = tracing.NewTransport(transport)
96 }
97 j, _ := cookiejar.New(nil)
98 defaultSender = &http.Client{Jar: j, Transport: roundTripper}
99 })
100 return defaultSender
101 }
102