4949import java .util .List ;
5050import java .util .Map ;
5151
52+ import javax .annotation .Priority ;
5253import javax .ws .rs .Priorities ;
5354import javax .ws .rs .client .Client ;
54- import javax .ws .rs .client .ClientBuilder ;
5555import javax .ws .rs .client .ClientRequestContext ;
5656import javax .ws .rs .client .ClientRequestFilter ;
5757import javax .ws .rs .client .ClientResponseContext ;
6666import javax .ws .rs .core .MultivaluedMap ;
6767import javax .ws .rs .core .Response ;
6868
69- import javax .annotation .Priority ;
70-
7169import org .glassfish .jersey .client .ClientProperties ;
7270import org .glassfish .jersey .client .internal .LocalizationMessages ;
7371
@@ -222,16 +220,22 @@ public void filter(ClientRequestContext request, ClientResponseContext response)
222220 Type result = null ; // which authentication is requested: BASIC or DIGEST
223221 boolean authenticate ;
224222
223+ // If the server requests both BASIC and DIGEST, prefer DIGEST since it's stronger
224+ // (see https://tools.ietf.org/html/rfc2617#section-4.6)
225225 if (response .getStatus () == Response .Status .UNAUTHORIZED .getStatusCode ()) {
226- String authString = response .getHeaders ().getFirst (HttpHeaders .WWW_AUTHENTICATE );
227- if (authString != null ) {
228- final String upperCaseAuth = authString .trim ().toUpperCase ();
229- if (upperCaseAuth .startsWith ("BASIC" )) {
230- result = Type .BASIC ;
231- } else if (upperCaseAuth .startsWith ("DIGEST" )) {
232- result = Type .DIGEST ;
233- } else {
234- // unknown authentication -> this filter cannot authenticate with this method
226+ List <String > authStrings = response .getHeaders ().get (HttpHeaders .WWW_AUTHENTICATE );
227+ if (authStrings != null ) {
228+ for (String authString : authStrings ) {
229+ final String upperCaseAuth = authString .trim ().toUpperCase ();
230+ if (result == null && upperCaseAuth .startsWith ("BASIC" )) {
231+ result = Type .BASIC ;
232+ } else if (upperCaseAuth .startsWith ("DIGEST" )) {
233+ result = Type .DIGEST ;
234+ }
235+ }
236+
237+ if (result == null ) {
238+ // unknown authentication -> this filter cannot authenticate with this method
235239 return ;
236240 }
237241 }
@@ -292,7 +296,7 @@ private void updateCache(ClientRequestContext request, boolean success, Type ope
292296 * @param newAuthorizationHeader {@code Authorization} header that should be added to the new request.
293297 * @return {@code true} is the authentication was successful ({@code true} if 401 response code was not returned;
294298 * {@code false} otherwise).
295- * @throws IOException
299+ * @throws IOException
296300 */
297301 static boolean repeatRequest (ClientRequestContext request , ClientResponseContext response , String newAuthorizationHeader )
298302 throws IOException {
@@ -304,7 +308,7 @@ static boolean repeatRequest(ClientRequestContext request, ClientResponseContext
304308 response .getEntityStream ().close ();
305309 response .setEntityStream (null );
306310 }
307-
311+
308312 Client client = request .getClient ();
309313 String method = request .getMethod ();
310314 MediaType mediaType = request .getMediaType ();
@@ -328,6 +332,12 @@ static boolean repeatRequest(ClientRequestContext request, ClientResponseContext
328332
329333 builder .property (REQUEST_PROPERTY_FILTER_REUSED , "true" );
330334
335+ // Copy other properties, if any, from the original request
336+ for (String propertyName : request .getPropertyNames ()) {
337+ Object propertyValue = request .getProperty (propertyName );
338+ builder .property (propertyName , propertyValue );
339+ }
340+
331341 Invocation invocation ;
332342 if (request .getEntity () == null ) {
333343 invocation = builder .build (method );
0 commit comments