1 // Package ldntlm allows you to configure the SDK to connect to LaunchDarkly through a proxy server that 2 // uses NTLM authentication. The standard Go HTTP client proxy mechanism does not support this. The 3 // implementation uses this package: github.com/launchdarkly/go-ntlm-proxy-auth 4 // 5 // See NewNTLMProxyHTTPClientFactory for more details. 6 package ldntlm 7 8 import ( 9 "errors" 10 "fmt" 11 "net/http" 12 "net/url" 13 14 ntlm "github.com/launchdarkly/go-ntlm-proxy-auth" 15 16 "github.com/launchdarkly/go-server-sdk/v6/ldhttp" 17 ) 18 19 // NewNTLMProxyHTTPClientFactory returns a factory function for creating an HTTP client that will 20 // connect through an NTLM-authenticated proxy server. 21 // 22 // To use this with the SDK, pass the factory function to HTTPConfigurationBuilder.HTTPClientFactory: 23 // 24 // clientFactory, err := ldntlm.NewNTLMProxyHTTPClientFactory("http://my-proxy.com", "username", 25 // "password", "domain") 26 // if err != nil { 27 // // there's some configuration problem such as an invalid proxy URL 28 // } 29 // config := ld.Config{ 30 // HTTP: ldcomponents.HTTPConfiguration().HTTPClientFactory(clientFactory), 31 // } 32 // client, err := ld.MakeCustomClient("sdk-key", config, 5*time.Second) 33 // 34 // You can also specify TLS configuration options from the ldhttp package, if you are connecting to 35 // the proxy securely: 36 // 37 // clientFactory, err := ldntlm.NewNTLMProxyHTTPClientFactory("http://my-proxy.com", "username", 38 // "password", "domain", ldhttp.CACertFileOption("extra-ca-cert.pem")) 39 func NewNTLMProxyHTTPClientFactory(proxyURL, username, password, domain string, 40 options ...ldhttp.TransportOption) (func() *http.Client, error) { 41 if proxyURL == "" || username == "" || password == "" { 42 return nil, errors.New("ProxyURL, username, and password are required") 43 } 44 parsedProxyURL, err := url.Parse(proxyURL) 45 if err != nil { 46 return nil, fmt.Errorf("invalid proxy URL %s: %s", proxyURL, err) 47 } 48 // Try creating a transport with these options just to make sure it's valid before we get any farther 49 if _, _, err := ldhttp.NewHTTPTransport(options...); err != nil { 50 return nil, err 51 } 52 return func() *http.Client { 53 client := *http.DefaultClient 54 if transport, dialer, err := ldhttp.NewHTTPTransport(options...); err == nil { 55 transport.DialContext = ntlm.NewNTLMProxyDialContext(dialer, *parsedProxyURL, 56 username, password, domain, transport.TLSClientConfig) 57 client.Transport = transport 58 } 59 return &client 60 }, nil 61 } 62