49
49
import java .util .List ;
50
50
import java .util .Map ;
51
51
52
+ import javax .annotation .Priority ;
52
53
import javax .ws .rs .Priorities ;
53
54
import javax .ws .rs .client .Client ;
54
- import javax .ws .rs .client .ClientBuilder ;
55
55
import javax .ws .rs .client .ClientRequestContext ;
56
56
import javax .ws .rs .client .ClientRequestFilter ;
57
57
import javax .ws .rs .client .ClientResponseContext ;
66
66
import javax .ws .rs .core .MultivaluedMap ;
67
67
import javax .ws .rs .core .Response ;
68
68
69
- import javax .annotation .Priority ;
70
-
71
69
import org .glassfish .jersey .client .ClientProperties ;
72
70
import org .glassfish .jersey .client .internal .LocalizationMessages ;
73
71
@@ -294,8 +292,16 @@ private void updateCache(ClientRequestContext request, boolean success, Type ope
294
292
* {@code false} otherwise).
295
293
*/
296
294
static boolean repeatRequest (ClientRequestContext request , ClientResponseContext response , String newAuthorizationHeader ) {
297
- Client client = request .getClient ();
295
+ // If the failed response has an entity stream, close it. We must do this to avoid leaking a connection
296
+ // when we replace the entity stream of the failed response with that of the repeated response (see below).
297
+ // Notice that by closing the entity stream before sending the repeated request we allow the connection allocated
298
+ // to the failed request to be reused, if possible, for the repeated request.
299
+ if (response .hasEntity ()) {
300
+ discardInputAndClose (response .getEntityStream ());
301
+ response .setEntityStream (null );
302
+ }
298
303
304
+ Client client = request .getClient ();
299
305
String method = request .getMethod ();
300
306
MediaType mediaType = request .getMediaType ();
301
307
URI lUri = request .getUri ();
@@ -318,6 +324,12 @@ static boolean repeatRequest(ClientRequestContext request, ClientResponseContext
318
324
319
325
builder .property (REQUEST_PROPERTY_FILTER_REUSED , "true" );
320
326
327
+ // Copy other properties, if any, from the original request
328
+ for (String propertyName : request .getPropertyNames ()) {
329
+ Object propertyValue = request .getProperty (propertyName );
330
+ builder .property (propertyName , propertyValue );
331
+ }
332
+
321
333
Invocation invocation ;
322
334
if (request .getEntity () == null ) {
323
335
invocation = builder .build (method );
@@ -443,4 +455,23 @@ static Credentials getCredentials(ClientRequestContext request, Credentials defa
443
455
return specificCredentials != null ? specificCredentials : defaultCredentials ;
444
456
}
445
457
}
458
+
459
+ private static void discardInputAndClose (InputStream is ) {
460
+ byte [] buf = new byte [4096 ];
461
+ try {
462
+ while (true ) {
463
+ if (is .read (buf ) <= 0 ) {
464
+ break ;
465
+ }
466
+ }
467
+ } catch (IOException ex ) {
468
+ // ignore
469
+ } finally {
470
+ try {
471
+ is .close ();
472
+ } catch (IOException ex ) {
473
+ // ignore
474
+ }
475
+ }
476
+ }
446
477
}
0 commit comments