405 } |
406 } |
406 } |
407 } |
407 |
408 |
408 @Override |
409 @Override |
409 public <T> CompletableFuture<HttpResponse<T>> |
410 public <T> CompletableFuture<HttpResponse<T>> |
410 sendAsync(HttpRequest req, BodyHandler<T> responseHandler) |
411 sendAsync(HttpRequest userRequest, BodyHandler<T> responseHandler) |
411 { |
412 { |
412 AccessControlContext acc = null; |
413 AccessControlContext acc = null; |
413 if (System.getSecurityManager() != null) |
414 if (System.getSecurityManager() != null) |
414 acc = AccessController.getContext(); |
415 acc = AccessController.getContext(); |
415 |
416 |
|
417 // Clone the, possibly untrusted, HttpRequest |
|
418 HttpRequestImpl requestImpl = new HttpRequestImpl(userRequest, proxySelector, acc); |
|
419 if (requestImpl.method().equals("CONNECT")) |
|
420 throw new IllegalArgumentException("Unsupported method CONNECT"); |
|
421 |
416 long start = DEBUGELAPSED ? System.nanoTime() : 0; |
422 long start = DEBUGELAPSED ? System.nanoTime() : 0; |
417 reference(); |
423 reference(); |
418 try { |
424 try { |
419 debug.log(Level.DEBUG, "ClientImpl (async) send %s", req); |
425 debug.log(Level.DEBUG, "ClientImpl (async) send %s", userRequest); |
420 |
426 |
421 MultiExchange<Void,T> mex = new MultiExchange<>(req, this, responseHandler, acc); |
427 MultiExchange<Void,T> mex = new MultiExchange<>(userRequest, |
|
428 requestImpl, |
|
429 this, |
|
430 responseHandler, |
|
431 acc); |
422 CompletableFuture<HttpResponse<T>> res = |
432 CompletableFuture<HttpResponse<T>> res = |
423 mex.responseAsync().whenComplete((b,t) -> unreference()); |
433 mex.responseAsync().whenComplete((b,t) -> unreference()); |
424 if (DEBUGELAPSED) { |
434 if (DEBUGELAPSED) { |
425 res = res.whenComplete( |
435 res = res.whenComplete( |
426 (b,t) -> debugCompleted("ClientImpl (async)", start, req)); |
436 (b,t) -> debugCompleted("ClientImpl (async)", start, userRequest)); |
427 } |
437 } |
428 // makes sure that any dependent actions happen in the executor |
438 // makes sure that any dependent actions happen in the executor |
429 if (acc != null) { |
439 if (acc != null) { |
430 res.whenCompleteAsync((r, t) -> { /* do nothing */}, |
440 res.whenCompleteAsync((r, t) -> { /* do nothing */}, |
431 new PrivilegedExecutor(executor, acc)); |
441 new PrivilegedExecutor(executor, acc)); |
432 } |
442 } |
433 |
443 |
434 return res; |
444 return res; |
435 } catch(Throwable t) { |
445 } catch(Throwable t) { |
436 unreference(); |
446 unreference(); |
437 debugCompleted("ClientImpl (async)", start, req); |
447 debugCompleted("ClientImpl (async)", start, userRequest); |
438 throw t; |
448 throw t; |
439 } |
449 } |
440 } |
450 } |
441 |
451 |
442 @Override |
452 @Override |
443 public <U, T> CompletableFuture<U> |
453 public <U, T> CompletableFuture<U> |
444 sendAsync(HttpRequest req, MultiSubscriber<U, T> responseHandler) { |
454 sendAsync(HttpRequest userRequest, MultiSubscriber<U, T> responseHandler) { |
445 AccessControlContext acc = null; |
455 AccessControlContext acc = null; |
446 if (System.getSecurityManager() != null) |
456 if (System.getSecurityManager() != null) |
447 acc = AccessController.getContext(); |
457 acc = AccessController.getContext(); |
448 |
458 |
|
459 // Clone the, possibly untrusted, HttpRequest |
|
460 HttpRequestImpl requestImpl = new HttpRequestImpl(userRequest, proxySelector, acc); |
|
461 if (requestImpl.method().equals("CONNECT")) |
|
462 throw new IllegalArgumentException("Unsupported method CONNECT"); |
|
463 |
449 long start = DEBUGELAPSED ? System.nanoTime() : 0; |
464 long start = DEBUGELAPSED ? System.nanoTime() : 0; |
450 reference(); |
465 reference(); |
451 try { |
466 try { |
452 debug.log(Level.DEBUG, "ClientImpl (async) send multi %s", req); |
467 debug.log(Level.DEBUG, "ClientImpl (async) send multi %s", userRequest); |
453 |
468 |
454 MultiExchange<U,T> mex = new MultiExchange<>(req, this, responseHandler, acc); |
469 MultiExchange<U,T> mex = new MultiExchange<>(userRequest, |
|
470 requestImpl, |
|
471 this, |
|
472 responseHandler, |
|
473 acc); |
455 CompletableFuture<U> res = mex.multiResponseAsync() |
474 CompletableFuture<U> res = mex.multiResponseAsync() |
456 .whenComplete((b,t) -> unreference()); |
475 .whenComplete((b,t) -> unreference()); |
457 if (DEBUGELAPSED) { |
476 if (DEBUGELAPSED) { |
458 res = res.whenComplete( |
477 res = res.whenComplete( |
459 (b,t) -> debugCompleted("ClientImpl (async)", start, req)); |
478 (b,t) -> debugCompleted("ClientImpl (async)", start, userRequest)); |
460 } |
479 } |
461 // makes sure that any dependent actions happen in the executor |
480 // makes sure that any dependent actions happen in the executor |
462 if (acc != null) { |
481 if (acc != null) { |
463 res.whenCompleteAsync((r, t) -> { /* do nothing */}, |
482 res.whenCompleteAsync((r, t) -> { /* do nothing */}, |
464 new PrivilegedExecutor(executor, acc)); |
483 new PrivilegedExecutor(executor, acc)); |
465 } |
484 } |
466 |
485 |
467 return res; |
486 return res; |
468 } catch(Throwable t) { |
487 } catch(Throwable t) { |
469 unreference(); |
488 unreference(); |
470 debugCompleted("ClientImpl (async)", start, req); |
489 debugCompleted("ClientImpl (async)", start, userRequest); |
471 throw t; |
490 throw t; |
472 } |
491 } |
473 } |
492 } |
474 |
493 |
475 // Main loop for this client's selector |
494 // Main loop for this client's selector |