Allow the same Jersey client to be used for both authenticated and non-authenticated URLs (#3858)

Signed-off-by: agherardi <alessandro.gherardi@yahoo.com>
diff --git a/connectors/apache-connector/src/test/java/org/glassfish/jersey/apache/connector/AuthTest.java b/connectors/apache-connector/src/test/java/org/glassfish/jersey/apache/connector/AuthTest.java
index e613411..b2289c1 100644
--- a/connectors/apache-connector/src/test/java/org/glassfish/jersey/apache/connector/AuthTest.java
+++ b/connectors/apache-connector/src/test/java/org/glassfish/jersey/apache/connector/AuthTest.java
@@ -149,6 +149,11 @@
         }
 
         @GET
+        @Path("noauth")
+        public String get() {
+            return "GET";
+        }
+
         @Path("digest")
         public String getDigest(@Context HttpHeaders h) {
             String value = h.getRequestHeaders().getFirst("Authorization");
@@ -296,6 +301,17 @@
     }
 
     @Test
+    public void testAuthGetBasicNoChallenge() {
+        ClientConfig cc = new ClientConfig();
+        cc.connectorProvider(new ApacheConnectorProvider());
+        Client client = ClientBuilder.newClient(cc);
+        client.register(HttpAuthenticationFeature.basicBuilder().build());
+        WebTarget r = client.target(getBaseUri()).path("test/noauth");
+
+        assertEquals("GET", r.request().get(String.class));
+    }
+
+    @Test
     public void testAuthGetWithDigestFilter() {
         ClientConfig cc = new ClientConfig();
         PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/authentication/BasicAuthenticator.java b/core-client/src/main/java/org/glassfish/jersey/client/authentication/BasicAuthenticator.java
index b08b074..8c4fc50 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/authentication/BasicAuthenticator.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/authentication/BasicAuthenticator.java
@@ -17,6 +17,8 @@
 package org.glassfish.jersey.client.authentication;
 
 import java.util.Base64;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 import javax.ws.rs.client.ClientRequestContext;
 import javax.ws.rs.client.ClientResponseContext;
@@ -33,6 +35,8 @@
  */
 final class BasicAuthenticator {
 
+    private static final Logger LOGGER = Logger.getLogger(BasicAuthenticator.class.getName());
+
     private final HttpAuthenticationFilter.Credentials defaultCredentials;
 
     /**
@@ -69,15 +73,15 @@
      * Adds authentication information to the request.
      *
      * @param request Request context.
-     * @throws RequestAuthenticationException in case that basic credentials missing or are in invalid format
      */
-    public void filterRequest(ClientRequestContext request) throws RequestAuthenticationException {
+    public void filterRequest(ClientRequestContext request) {
         HttpAuthenticationFilter.Credentials credentials = HttpAuthenticationFilter.getCredentials(request,
                 defaultCredentials, HttpAuthenticationFilter.Type.BASIC);
         if (credentials == null) {
-            throw new RequestAuthenticationException(LocalizationMessages.AUTHENTICATION_CREDENTIALS_MISSING_BASIC());
+            LOGGER.fine(LocalizationMessages.AUTHENTICATION_CREDENTIALS_NOT_PROVIDED_BASIC());
+        } else {
+            request.getHeaders().add(HttpHeaders.AUTHORIZATION, calculateAuthentication(credentials));
         }
-        request.getHeaders().add(HttpHeaders.AUTHORIZATION, calculateAuthentication(credentials));
     }
 
     /**
diff --git a/core-client/src/main/resources/org/glassfish/jersey/client/internal/localization.properties b/core-client/src/main/resources/org/glassfish/jersey/client/internal/localization.properties
index 12134f7..7e45210 100644
--- a/core-client/src/main/resources/org/glassfish/jersey/client/internal/localization.properties
+++ b/core-client/src/main/resources/org/glassfish/jersey/client/internal/localization.properties
@@ -16,6 +16,7 @@
 
 #brief.message.identifier=Message text, possibly with some attributes "{0}" etc.
 authentication.credentials.missing.basic=Credentials must be defined for basic authentication. Define username and password either when creating HttpAuthenticationFeature or use specific credentials for each request using the request property (see HttpAuthenticationFeature).
+authentication.credentials.not.provided.basic=No credentials are provided for basic authentication. Request will be sent without an Authorization header.
 authentication.credentials.missing.digest=Credentials must be defined for digest authentication. Define username and password either when creating HttpAuthenticationFeature or use specific credentials for each request using the request property (see HttpAuthenticationFeature).
 authentication.credentials.request.password.unsupported=Unsupported password type class. Password passed in the request property must be String or byte[].
 chunked.input.closed=Chunked input has been closed already.