2424import org .apache .hc .client5 .http .auth .CredentialsStore ;
2525import org .apache .hc .client5 .http .auth .UsernamePasswordCredentials ;
2626import org .apache .hc .client5 .http .impl .auth .BasicAuthCache ;
27- import org .apache .hc .client5 .http .impl .auth .BasicCredentialsProvider ;
2827import org .apache .hc .client5 .http .impl .auth .BasicScheme ;
2928import org .apache .hc .client5 .http .impl .auth .SystemDefaultCredentialsProvider ;
3029import org .apache .hc .client5 .http .impl .classic .BasicHttpClientResponseHandler ;
@@ -115,6 +114,22 @@ public final class Downloader {
115114 * The singleton instance of the downloader
116115 */
117116 private static final Downloader INSTANCE = new Downloader ();
117+ /**
118+ * The Credentials for the proxy when proxy authentication is configured in the Settings.
119+ */
120+ private Credentials proxyCreds = null ;
121+ /**
122+ * A BasicScheme initialized with the proxy-credentials when proxy authentication is configured in the Settings.
123+ */
124+ private BasicScheme proxyPreEmptAuth = null ;
125+ /**
126+ * The AuthScope for the proxy when proxy authentication is configured in the Settings.
127+ */
128+ private AuthScope proxyAuthScope = null ;
129+ /**
130+ * The HttpHost for the proxy when proxy authentication is configured in the Settings.
131+ */
132+ private HttpHost proxyHttpHost = null ;
118133
119134 private Downloader () {
120135 // Singleton class
@@ -179,12 +194,12 @@ public void configure(Settings settings) throws InvalidSettingException {
179194 if (settings .getString (Settings .KEYS .PROXY_USERNAME ) != null ) {
180195 final String proxyuser = settings .getString (Settings .KEYS .PROXY_USERNAME );
181196 final char [] proxypass = settings .getString (Settings .KEYS .PROXY_PASSWORD ).toCharArray ();
182- final HttpHost theProxy = new HttpHost (null , proxyHost , proxyPort );
183- final Credentials creds = new UsernamePasswordCredentials (proxyuser , proxypass );
184- credentialsProvider . setCredentials (
185- new AuthScope ( theProxy ),
186- creds
187- );
197+ this . proxyHttpHost = new HttpHost (null , proxyHost , proxyPort );
198+ this . proxyCreds = new UsernamePasswordCredentials (proxyuser , proxypass );
199+ this . proxyAuthScope = new AuthScope ( proxyHttpHost );
200+ this . proxyPreEmptAuth = new BasicScheme ();
201+ this . proxyPreEmptAuth . initPreemptive ( proxyCreds );
202+ tryConfigureProxyCredentials ( credentialsProvider , authCache );
188203 }
189204 }
190205 tryAddRetireJSCredentials (settings , credentialsProvider , authCache );
@@ -422,17 +437,21 @@ public void fetchFile(URL url, File outputPath, boolean useProxy, String userKey
422437 throw new DownloadFailedException ("Unsupported protocol in the URL; only file, http and https are supported" );
423438 }
424439 try {
425- final HttpClientContext context = HttpClientContext .create ();
426- final BasicCredentialsProvider localCredentials = new BasicCredentialsProvider ();
440+ final HttpClientContext dedicatedAuthContext = HttpClientContext .create ();
441+ final CredentialsStore dedicatedCredentialStore = new SystemDefaultCredentialsProvider ();
427442 final HttpHost scopeHost = new HttpHost (url .getProtocol (), url .getHost (), url .getPort ());
428- final AuthCache dedicated = new BasicAuthCache ();
429- addCredentials (localCredentials , scopeHost , url .toString (), settings .getString (userKey ), settings .getString (passwordKey ).toCharArray (), dedicated );
430- context .setCredentialsProvider (localCredentials );
431- context .setAuthCache (dedicated );
443+ final AuthCache dedicatedAuthCache = new BasicAuthCache ();
444+ addCredentials (dedicatedCredentialStore , scopeHost , url .toString (), settings .getString (userKey ),
445+ settings .getString (passwordKey ).toCharArray (), dedicatedAuthCache );
446+ if (useProxy && proxyAuthScope != null ) {
447+ tryConfigureProxyCredentials (dedicatedCredentialStore , dedicatedAuthCache );
448+ }
449+ dedicatedAuthContext .setCredentialsProvider (dedicatedCredentialStore );
450+ dedicatedAuthContext .setAuthCache (dedicatedAuthCache );
432451 try (CloseableHttpClient hc = useProxy ? httpClientBuilder .build () : httpClientBuilderExplicitNoproxy .build ()) {
433452 final BasicClassicHttpRequest req = new BasicClassicHttpRequest (Method .GET , url .toURI ());
434453 final SaveToFileResponseHandler responseHandler = new SaveToFileResponseHandler (outputPath );
435- hc .execute (req , context , responseHandler );
454+ hc .execute (req , dedicatedAuthContext , responseHandler );
436455 }
437456 } catch (HttpResponseException hre ) {
438457 wrapAndThrowHttpResponseException (url .toString (), hre );
@@ -450,6 +469,18 @@ public void fetchFile(URL url, File outputPath, boolean useProxy, String userKey
450469 }
451470 }
452471
472+ /**
473+ * Add the proxy credentials to the CredentialsProvider and AuthCache instances when proxy-authentication is configured in the settings.
474+ * @param credentialsProvider The credentialStore to configure the credentials in
475+ * @param authCache The AuthCache to cache the pre-empted credentials in
476+ */
477+ private void tryConfigureProxyCredentials (@ NotNull CredentialsStore credentialsProvider , @ NotNull AuthCache authCache ) {
478+ if (proxyPreEmptAuth != null ) {
479+ credentialsProvider .setCredentials (proxyAuthScope , proxyCreds );
480+ authCache .put (proxyHttpHost , proxyPreEmptAuth );
481+ }
482+ }
483+
453484 /**
454485 * Posts a payload to the URL and returns the response as a string.
455486 *
0 commit comments