public abstract class CloseableHttpClient implements HttpClient, Closeable { private final Log log = LogFactory.getLog(getClass()); protected abstract CloseableHttpResponse doExecute(HttpHost target, HttpRequest request, HttpContext context) throws IOException, ClientProtocolException; /** * {@inheritDoc} */ public CloseableHttpResponse execute( final HttpHost target, final HttpRequest request, final HttpContext context) throws IOException, ClientProtocolException { return doExecute(target, request, context); } /** * {@inheritDoc} */ public CloseableHttpResponse execute( final HttpUriRequest request, final HttpContext context) throws IOException, ClientProtocolException { Args.notNull(request, "HTTP request"); return doExecute(determineTarget(request), request, context); } private static HttpHost determineTarget(final HttpUriRequest request) throws ClientProtocolException { // A null target may be acceptable if there is a default target. // Otherwise, the null target is detected in the director. HttpHost target = null; final URI requestURI = request.getURI(); if (requestURI.isAbsolute()) { target = URIUtils.extractHost(requestURI); if (target == null) { throw new ClientProtocolException("URI does not specify a valid host name: " + requestURI); } } return target; } /** * {@inheritDoc} */ public CloseableHttpResponse execute( final HttpUriRequest request) throws IOException, ClientProtocolException { return execute(request, (HttpContext) null); } /** * {@inheritDoc} */ public CloseableHttpResponse execute( final HttpHost target, final HttpRequest request) throws IOException, ClientProtocolException { return doExecute(target, request, (HttpContext) null); } /** * Executes a request using the default context and processes the * response using the given response handler. The content entity associated * with the response is fully consumed and the underlying connection is * released back to the connection manager automatically in all cases * relieving individual {@link ResponseHandler}s from having to manage * resource deallocation internally. * * @param request the request to execute * @param responseHandler the response handler * * @return the response object as generated by the response handler. * @throws IOException in case of a problem or the connection was aborted * @throws ClientProtocolException in case of an http protocol error */ public <T> T execute(final HttpUriRequest request, final ResponseHandler<? extends T> responseHandler) throws IOException, ClientProtocolException { return execute(request, responseHandler, null); } /** * Executes a request using the default context and processes the * response using the given response handler. The content entity associated * with the response is fully consumed and the underlying connection is * released back to the connection manager automatically in all cases * relieving individual {@link ResponseHandler}s from having to manage * resource deallocation internally. * * @param request the request to execute * @param responseHandler the response handler * @param context the context to use for the execution, or * <code>null</code> to use the default context * * @return the response object as generated by the response handler. * @throws IOException in case of a problem or the connection was aborted * @throws ClientProtocolException in case of an http protocol error */ public <T> T execute(final HttpUriRequest request, final ResponseHandler<? extends T> responseHandler, final HttpContext context) throws IOException, ClientProtocolException { final HttpHost target = determineTarget(request); return execute(target, request, responseHandler, context); } /** * Executes a request using the default context and processes the * response using the given response handler. The content entity associated * with the response is fully consumed and the underlying connection is * released back to the connection manager automatically in all cases * relieving individual {@link ResponseHandler}s from having to manage * resource deallocation internally. * * @param target the target host for the request. * Implementations may accept <code>null</code> * if they can still determine a route, for example * to a default target or by inspecting the request. * @param request the request to execute * @param responseHandler the response handler * * @return the response object as generated by the response handler. * @throws IOException in case of a problem or the connection was aborted * @throws ClientProtocolException in case of an http protocol error */ public <T> T execute(final HttpHost target, final HttpRequest request, final ResponseHandler<? extends T> responseHandler) throws IOException, ClientProtocolException { return execute(target, request, responseHandler, null); } /** * Executes a request using the default context and processes the * response using the given response handler. The content entity associated * with the response is fully consumed and the underlying connection is * released back to the connection manager automatically in all cases * relieving individual {@link ResponseHandler}s from having to manage * resource deallocation internally. * * @param target the target host for the request. * Implementations may accept <code>null</code> * if they can still determine a route, for example * to a default target or by inspecting the request. * @param request the request to execute * @param responseHandler the response handler * @param context the context to use for the execution, or * <code>null</code> to use the default context * * @return the response object as generated by the response handler. * @throws IOException in case of a problem or the connection was aborted * @throws ClientProtocolException in case of an http protocol error */ public <T> T execute(final HttpHost target, final HttpRequest request, final ResponseHandler<? extends T> responseHandler, final HttpContext context) throws IOException, ClientProtocolException { Args.notNull(responseHandler, "Response handler"); final HttpResponse response = execute(target, request, context); final T result; try { result = responseHandler.handleResponse(response); } catch (final Exception t) { final HttpEntity entity = response.getEntity(); try { EntityUtils.consume(entity); } catch (final Exception t2) { // Log this exception. The original exception is more // important and will be thrown to the caller. this.log.warn("Error consuming content after an exception.", t2); } if (t instanceof RuntimeException) { throw (RuntimeException) t; } if (t instanceof IOException) { throw (IOException) t; } throw new UndeclaredThrowableException(t); } // Handling the response was successful. Ensure that the content has // been fully consumed. final HttpEntity entity = response.getEntity(); EntityUtils.consume(entity); return result; } }