@@ -124,65 +124,83 @@ func NewAccessTokenOrLegacyToken(token string, host string, skipSSLValidation bo
124124 }
125125}
126126
127+ // createProxyAuthTransport creates an HTTP transport with proxy authentication
128+ func createProxyAuthTransport (config ClientConfig ) (http.RoundTripper , error ) {
129+ // Validate required fields for proxy authentication
130+ if config .ProxyAuthConfig .ProxyURL == "" || config .ProxyAuthConfig .Username == "" || config .ProxyAuthConfig .Password == "" {
131+ return nil , fmt .Errorf ("proxy URL, username, and password are required when proxy authentication is specified" )
132+ }
133+
134+ // Parse proxy URL
135+ proxyURL , err := url .Parse (config .ProxyAuthConfig .ProxyURL )
136+ if err != nil {
137+ return nil , fmt .Errorf ("failed to parse proxy URL: %w" , err )
138+ }
139+
140+ // Create base transport
141+ transport := & http.Transport {
142+ TLSClientConfig : & tls.Config {
143+ InsecureSkipVerify : config .SkipSSLValidation ,
144+ },
145+ Proxy : http .ProxyURL (proxyURL ),
146+ }
147+
148+ // Create authenticator
149+ authenticator , err := NewProxyAuthenticator (config .ProxyAuthConfig )
150+ if err != nil {
151+ return nil , fmt .Errorf ("failed to create proxy authenticator: %w" , err )
152+ }
153+
154+ // Wrap transport with proxy authentication
155+ proxyAuthTransport , err := NewProxyAuthTransport (transport , authenticator )
156+ if err != nil {
157+ return nil , fmt .Errorf ("failed to initialize proxy authentication: %w" , err )
158+ }
159+ return proxyAuthTransport , nil
160+ }
161+
162+ // initializeClientServices initializes all service endpoints for the client
163+ func initializeClientServices (client * Client , lgr logger.Logger ) {
164+ client .Auth = & AuthService {client : * client }
165+ client .EULA = & EULAsService {client : * client }
166+ client .ProductFiles = & ProductFilesService {client : * client }
167+ client .ArtifactReferences = & ArtifactReferencesService {client : * client }
168+ client .FederationToken = & FederationTokenService {client : * client }
169+ client .FileGroups = & FileGroupsService {client : * client }
170+ client .Releases = & ReleasesService {client : * client , l : lgr }
171+ client .Products = & ProductsService {client : * client , l : lgr }
172+ client .UserGroups = & UserGroupsService {client : * client }
173+ client .SubscriptionGroups = & SubscriptionGroupsService {client : * client }
174+ client .ReleaseTypes = & ReleaseTypesService {client : * client }
175+ client .ReleaseDependencies = & ReleaseDependenciesService {client : * client }
176+ client .DependencySpecifiers = & DependencySpecifiersService {client : * client }
177+ client .ReleaseUpgradePaths = & ReleaseUpgradePathsService {client : * client }
178+ client .UpgradePathSpecifiers = & UpgradePathSpecifiersService {client : * client }
179+ client .PivnetVersions = & PivnetVersionsService {client : * client }
180+ }
181+
127182func NewClient (
128183 token AccessTokenService ,
129184 config ClientConfig ,
130185 lgr logger.Logger ,
131186) Client {
132187 baseURL := fmt .Sprintf ("%s%s" , config .Host , apiVersion )
133188
134- // Create proxy function based on ProxyAuthConfig or environment
135- proxyFunc := http .ProxyFromEnvironment
136- if config .ProxyAuthConfig .ProxyURL != "" {
137- proxyURL , err := url .Parse (config .ProxyAuthConfig .ProxyURL )
138- if err != nil {
139- lgr .Info ("Failed to parse proxy URL, falling back to environment proxy" , logger.Data {"error" : err .Error (), "proxy_url" : config .ProxyAuthConfig .ProxyURL })
140- } else {
141- proxyFunc = http .ProxyURL (proxyURL )
142- }
143- }
144-
145- // Create base transport for connection pooling
146189 baseTransport := & http.Transport {
147190 TLSClientConfig : & tls.Config {
148191 InsecureSkipVerify : config .SkipSSLValidation ,
149192 },
150- Proxy : proxyFunc ,
193+ Proxy : http . ProxyFromEnvironment ,
151194 }
152195
153- // Wrap with proxy authentication if configured
154- httpTransport := http .RoundTripper (baseTransport )
155- if config .ProxyAuthConfig .AuthType != "" {
156- if config .ProxyAuthConfig .ProxyURL == "" {
157- lgr .Info ("Proxy URL is required when proxy authentication is specified" , logger.Data {"auth_type" : string (config .ProxyAuthConfig .AuthType )})
158- } else if config .ProxyAuthConfig .Username == "" {
159- lgr .Info ("Proxy username is required when proxy authentication is specified" , logger.Data {"auth_type" : string (config .ProxyAuthConfig .AuthType )})
160- } else if config .ProxyAuthConfig .Password == "" {
161- lgr .Info ("Proxy password is required when proxy authentication is specified" , logger.Data {"auth_type" : string (config .ProxyAuthConfig .AuthType )})
162- } else {
163- authenticator , err := NewProxyAuthenticator (config .ProxyAuthConfig )
164- if err != nil {
165- lgr .Info ("Failed to create proxy authenticator" , logger.Data {"error" : err .Error (), "auth_type" : string (config .ProxyAuthConfig .AuthType )})
166- } else {
167- proxyAuthTransport , err := NewProxyAuthTransport (baseTransport , authenticator )
168- if err != nil {
169- lgr .Info ("Failed to initialize proxy authentication" , logger.Data {"error" : err .Error (), "auth_type" : string (config .ProxyAuthConfig .AuthType )})
170- } else {
171- httpTransport = proxyAuthTransport
172- }
173- }
174- }
175- }
176-
177- // Create HTTP client and download client with the same transport
178196 httpClient := & http.Client {
179197 Timeout : 10 * time .Minute ,
180- Transport : httpTransport ,
198+ Transport : baseTransport ,
181199 }
182200
183201 downloadClient := & http.Client {
184202 Timeout : 0 ,
185- Transport : httpTransport ,
203+ Transport : baseTransport ,
186204 }
187205
188206 ranger := download .NewRanger (concurrentDownloads )
@@ -202,26 +220,61 @@ func NewClient(
202220 HTTP : httpClient ,
203221 }
204222
205- client .Auth = & AuthService {client : client }
206- client .EULA = & EULAsService {client : client }
207- client .ProductFiles = & ProductFilesService {client : client }
208- client .ArtifactReferences = & ArtifactReferencesService {client : client }
209- client .FederationToken = & FederationTokenService {client : client }
210- client .FileGroups = & FileGroupsService {client : client }
211- client .Releases = & ReleasesService {client : client , l : lgr }
212- client .Products = & ProductsService {client : client , l : lgr }
213- client .UserGroups = & UserGroupsService {client : client }
214- client .SubscriptionGroups = & SubscriptionGroupsService {client : client }
215- client .ReleaseTypes = & ReleaseTypesService {client : client }
216- client .ReleaseDependencies = & ReleaseDependenciesService {client : client }
217- client .DependencySpecifiers = & DependencySpecifiersService {client : client }
218- client .ReleaseUpgradePaths = & ReleaseUpgradePathsService {client : client }
219- client .UpgradePathSpecifiers = & UpgradePathSpecifiersService {client : client }
220- client .PivnetVersions = & PivnetVersionsService {client : client }
223+ initializeClientServices (& client , lgr )
221224
222225 return client
223226}
224227
228+ // NewClientWithProxy creates a new Pivnet client with optional proxy authentication support
229+ func NewClientWithProxy (
230+ token AccessTokenService ,
231+ config ClientConfig ,
232+ lgr logger.Logger ,
233+ ) (Client , error ) {
234+ var transport http.RoundTripper
235+ var err error
236+
237+ // If proxy authentication is configured, use it; otherwise use standard transport
238+ if config .ProxyAuthConfig .AuthType != "" {
239+ transport , err = createProxyAuthTransport (config )
240+ if err != nil {
241+ return Client {}, err
242+ }
243+ } else {
244+ // Use standard transport with environment proxy support
245+ transport = & http.Transport {
246+ TLSClientConfig : & tls.Config {
247+ InsecureSkipVerify : config .SkipSSLValidation ,
248+ },
249+ Proxy : http .ProxyFromEnvironment ,
250+ }
251+ }
252+
253+ client := Client {
254+ baseURL : fmt .Sprintf ("%s%s" , config .Host , apiVersion ),
255+ token : token ,
256+ userAgent : config .UserAgent ,
257+ logger : lgr ,
258+ HTTP : & http.Client {
259+ Timeout : 10 * time .Minute ,
260+ Transport : transport ,
261+ },
262+ downloader : download.Client {
263+ HTTPClient : & http.Client {
264+ Timeout : 0 ,
265+ Transport : transport ,
266+ },
267+ Ranger : download .NewRanger (concurrentDownloads ),
268+ Logger : lgr ,
269+ Timeout : 30 * time .Second ,
270+ },
271+ }
272+
273+ initializeClientServices (& client , lgr )
274+
275+ return client , nil
276+ }
277+
225278func (c Client ) CreateRequest (
226279 requestType string ,
227280 endpoint string ,
0 commit comments