@Test(expected=ClientProtocolException.class) public void testBasicAuthenticationFailureOnNonRepeatablePost() throws Exception { this.serverBootstrap.registerHandler("*", new AuthHandler()); final HttpHost target = start(); final HttpPost httppost = new HttpPost("/"); httppost.setEntity(new InputStreamEntity( new ByteArrayInputStream( new byte[] { 0,1,2,3,4,5,6,7,8,9 }), -1)); final HttpClientContext context = HttpClientContext.create(); final TestCredentialsProvider credsProvider = new TestCredentialsProvider( new UsernamePasswordCredentials("test", "test")); context.setCredentialsProvider(credsProvider); try { this.httpclient.execute(target, httppost, context); Assert.fail("ClientProtocolException should have been thrown"); } catch (final ClientProtocolException ex) { final Throwable cause = ex.getCause(); Assert.assertNotNull(cause); Assert.assertTrue(cause instanceof NonRepeatableRequestException); throw ex; } }
@Test(expected=ClientProtocolException.class) public void testBasicAuthenticationFailureOnNonRepeatablePutDontExpectContinue() throws Exception { this.serverBootstrap.registerHandler("*", new AuthHandler()); final HttpHost target = start(); final RequestConfig config = RequestConfig.custom().setExpectContinueEnabled(true).build(); final HttpPut httpput = new HttpPut("/"); httpput.setConfig(config); httpput.setEntity(new InputStreamEntity( new ByteArrayInputStream( new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 } ), -1)); final HttpClientContext context = HttpClientContext.create(); final TestCredentialsProvider credsProvider = new TestCredentialsProvider( new UsernamePasswordCredentials("test", "boom")); context.setCredentialsProvider(credsProvider); try { this.httpclient.execute(target, httpput, context); Assert.fail("ClientProtocolException should have been thrown"); } catch (final ClientProtocolException ex) { final Throwable cause = ex.getCause(); Assert.assertNotNull(cause); Assert.assertTrue(cause instanceof NonRepeatableRequestException); throw ex; } }
/** * Execute request and retry in case of a recoverable I/O failure */ private HttpResponse tryExecute( final RoutedRequest req, final HttpContext context) throws HttpException, IOException { RequestWrapper wrapper = req.getRequest(); HttpRoute route = req.getRoute(); HttpResponse response = null; Exception retryReason = null; for (;;) { // Increment total exec count (with redirects) execCount++; // Increment exec count for this particular request wrapper.incrementExecCount(); if (!wrapper.isRepeatable()) { this.log.debug("Cannot retry non-repeatable request"); if (retryReason != null) { throw new NonRepeatableRequestException("Cannot retry request " + "with a non-repeatable request entity. The cause lists the " + "reason the original request failed.", retryReason); } else { throw new NonRepeatableRequestException("Cannot retry request " + "with a non-repeatable request entity."); } } try { if (!managedConn.isOpen()) { // If we have a direct route to the target host // just re-open connection and re-try the request if (!route.isTunnelled()) { this.log.debug("Reopening the direct connection."); managedConn.open(route, context, params); } else { // otherwise give up this.log.debug("Proxied connection. Need to start over."); break; } } if (this.log.isDebugEnabled()) { this.log.debug("Attempt " + execCount + " to execute request"); } response = requestExec.execute(wrapper, managedConn, context); break; } catch (IOException ex) { this.log.debug("Closing the connection."); try { managedConn.close(); } catch (IOException ignore) { } if (retryHandler.retryRequest(ex, wrapper.getExecCount(), context)) { if (this.log.isInfoEnabled()) { this.log.info("I/O exception ("+ ex.getClass().getName() + ") caught when processing request: " + ex.getMessage()); } if (this.log.isDebugEnabled()) { this.log.debug(ex.getMessage(), ex); } this.log.info("Retrying request"); retryReason = ex; } else { throw ex; } } } return response; }
public CloseableHttpResponse execute( final HttpRoute route, final HttpRequestWrapper request, final HttpClientContext context, final HttpExecutionAware execAware) throws IOException, HttpException { Args.notNull(route, "HTTP route"); Args.notNull(request, "HTTP request"); Args.notNull(context, "HTTP context"); final Header[] origheaders = request.getAllHeaders(); for (int execCount = 1;; execCount++) { try { return this.requestExecutor.execute(route, request, context, execAware); } catch (final IOException ex) { if (execAware != null && execAware.isAborted()) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Request has been aborted"); } throw ex; } if (retryHandler.retryRequest(ex, execCount, context)) { if (Log.isLoggable(TAG, Log.INFO)) { Log.i(TAG, "I/O exception ("+ ex.getClass().getName() + ") caught when processing request to " + route + ": " + ex.getMessage()); } if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, ex.getMessage(), ex); } if (!RequestEntityProxy.isRepeatable(request)) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Cannot retry non-repeatable request"); } final NonRepeatableRequestException nreex = new NonRepeatableRequestException( "Cannot retry request with a non-repeatable request entity"); nreex.initCause(ex); } request.setHeaders(origheaders); if (Log.isLoggable(TAG, Log.INFO)) { Log.i(TAG, "Retrying request to " + route); } } else { if (ex instanceof NoHttpResponseException) { final NoHttpResponseException updatedex = new NoHttpResponseException( route.getTargetHost().toHostString() + " failed to respond"); updatedex.setStackTrace(ex.getStackTrace()); throw updatedex; } else { throw ex; } } } } }
@Override public CloseableHttpResponse execute( final HttpRoute route, final HttpRequestWrapper request, final HttpClientContext context, final HttpExecutionAware execAware) throws IOException, HttpException { Args.notNull(route, "HTTP route"); Args.notNull(request, "HTTP request"); Args.notNull(context, "HTTP context"); final Header[] origheaders = request.getAllHeaders(); for (int execCount = 1;; execCount++) { try { return this.requestExecutor.execute(route, request, context, execAware); } catch (final IOException ex) { if (execAware != null && execAware.isAborted()) { this.log.debug("Request has been aborted"); throw ex; } if (retryHandler.retryRequest(ex, execCount, context)) { if (this.log.isInfoEnabled()) { this.log.info("I/O exception ("+ ex.getClass().getName() + ") caught when processing request to " + route + ": " + ex.getMessage()); } if (this.log.isDebugEnabled()) { this.log.debug(ex.getMessage(), ex); } if (!RequestEntityProxy.isRepeatable(request)) { this.log.debug("Cannot retry non-repeatable request"); throw new NonRepeatableRequestException("Cannot retry request " + "with a non-repeatable request entity", ex); } request.setHeaders(origheaders); if (this.log.isInfoEnabled()) { this.log.info("Retrying request to " + route); } } else { if (ex instanceof NoHttpResponseException) { final NoHttpResponseException updatedex = new NoHttpResponseException( route.getTargetHost().toHostString() + " failed to respond"); updatedex.setStackTrace(ex.getStackTrace()); throw updatedex; } else { throw ex; } } } } }
@Test(expected = NonRepeatableRequestException.class) public void testExecEntityEnclosingRequest() throws Exception { final HttpRoute route = new HttpRoute(target); final HttpClientContext context = new HttpClientContext(); final HttpPost post = new HttpPost("http://bar/test"); final InputStream instream0 = new ByteArrayInputStream(new byte[] {1, 2, 3}); post.setEntity(EntityBuilder.create() .setStream(instream0) .build()); final HttpRequestWrapper request = HttpRequestWrapper.wrap(post); final HttpResponse response1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, 401, "Huh?"); final InputStream instream1 = new ByteArrayInputStream(new byte[] {1, 2, 3}); response1.setEntity(EntityBuilder.create() .setStream(instream1) .build()); Mockito.when(managedConn.isOpen()).thenReturn(Boolean.TRUE); Mockito.when(managedConn.isStale()).thenReturn(Boolean.FALSE); Mockito.when(requestExecutor.execute( Mockito.same(request), Mockito.<HttpClientConnection>any(), Mockito.<HttpClientContext>any())).thenAnswer(new Answer<HttpResponse>() { @Override public HttpResponse answer(final InvocationOnMock invocationOnMock) throws Throwable { final Object[] args = invocationOnMock.getArguments(); final HttpEntityEnclosingRequest requestEE = (HttpEntityEnclosingRequest) args[0]; requestEE.getEntity().writeTo(new ByteArrayOutputStream()); return response1; } }); Mockito.when(reuseStrategy.keepAlive( Mockito.<HttpResponse>any(), Mockito.<HttpClientContext>any())).thenReturn(Boolean.TRUE); Mockito.when(targetAuthStrategy.isAuthenticationRequested( Mockito.eq(target), Mockito.same(response1), Mockito.<HttpClientContext>any())).thenReturn(Boolean.TRUE); mainClientExec.execute(route, request, context, execAware); }
@Test(expected = NonRepeatableRequestException.class) public void testNonRepeatableRequest() throws Exception { final HttpRoute route = new HttpRoute(target); final HttpPost post = new HttpPost("/test"); post.setEntity(EntityBuilder.create() .setStream(new ByteArrayInputStream(new byte[]{})) .build()); final HttpRequestWrapper request = HttpRequestWrapper.wrap(post); final HttpClientContext context = HttpClientContext.create(); Mockito.when(requestExecutor.execute( Mockito.eq(route), Mockito.same(request), Mockito.<HttpClientContext>any(), Mockito.<HttpExecutionAware>any())).thenAnswer(new Answer<Object>() { @Override public Object answer(final InvocationOnMock invocationOnMock) throws Throwable { final Object[] args = invocationOnMock.getArguments(); final HttpEntityEnclosingRequest req = (HttpEntityEnclosingRequest) args[1]; req.getEntity().writeTo(new ByteArrayOutputStream()); throw new IOException("Ka-boom"); } }); Mockito.when(retryHandler.retryRequest( Mockito.<IOException>any(), Mockito.eq(1), Mockito.<HttpContext>any())).thenReturn(Boolean.TRUE); try { retryExec.execute(route, request, context, execAware); } catch (final IOException ex) { Mockito.verify(requestExecutor, Mockito.times(1)).execute( Mockito.eq(route), Mockito.same(request), Mockito.same(context), Mockito.same(execAware)); throw ex; } }
/** * Execute request and retry in case of a recoverable I/O failure */ private HttpResponse tryExecute( final RoutedRequest req, final HttpContext context) throws HttpException, IOException { RequestWrapper wrapper = req.getRequest(); HttpRoute route = req.getRoute(); HttpResponse response = null; Exception retryReason = null; for (;;) { // Increment total exec count (with redirects) execCount++; // Increment exec count for this particular request wrapper.incrementExecCount(); if (!wrapper.isRepeatable()) { if (retryReason != null) { throw new NonRepeatableRequestException("Cannot retry request " + "with a non-repeatable request entity. The cause lists the " + "reason the original request failed." + retryReason); } else { throw new NonRepeatableRequestException("Cannot retry request " + "with a non-repeatable request entity."); } } try { if (!managedConn.isOpen()) { // If we have a direct route to the target host // just re-open connection and re-try the request if (!route.isTunnelled()) { if (DEBUG) { Logger.debug("Reopening the direct connection."); } managedConn.open(route, context, params); } else { // otherwise give up if (DEBUG) { Logger.debug("Proxied connection. Need to start over."); } break; } } response = requestExec.execute(wrapper, managedConn, context); break; } catch (IOException ex) { try { managedConn.close(); } catch (IOException ignore) { } if (retryHandler.retryRequest(ex, wrapper.getExecCount(), context)) { retryReason = ex; } else { throw ex; } } } return response; }
/** * Execute request and retry in case of a recoverable I/O failure */ private HttpResponse tryExecute( final RoutedRequest req, final HttpContext context) throws HttpException, IOException { RequestWrapper wrapper = req.getRequest(); HttpRoute route = req.getRoute(); HttpResponse response = null; Exception retryReason = null; for (;;) { // Increment total exec count (with redirects) execCount++; // Increment exec count for this particular request wrapper.incrementExecCount(); if (!wrapper.isRepeatable()) { if (Constants.DEBUG) { logger.debug("Cannot retry non-repeatable request"); } if (retryReason != null) { throw new NonRepeatableRequestException("Cannot retry request " + "with a non-repeatable request entity. The cause lists the " + "reason the original request failed." + retryReason); } else { throw new NonRepeatableRequestException("Cannot retry request " + "with a non-repeatable request entity."); } } try { if (!managedConn.isOpen()) { // If we have a direct route to the target host // just re-open connection and re-try the request if (!route.isTunnelled()) { if (Constants.DEBUG) { logger.debug("Reopening the direct connection."); } managedConn.open(route, context, params); } else { // otherwise give up if (Constants.DEBUG) { logger.debug("Proxied connection. Need to start over."); } break; } } if (Constants.DEBUG) { logger.debug("Attempt {} to execute request", execCount); } response = requestExec.execute(wrapper, managedConn, context); break; } catch (IOException ex) { if (Constants.DEBUG) { logger.debug("Closing the connection."); } try { managedConn.close(); } catch (IOException ignore) { } if (retryHandler.retryRequest(ex, wrapper.getExecCount(), context)) { if (Constants.DEBUG) { logger.debug("I/O exception ({}) caught when processing request: {}", ex.getClass().getName(), ex.getMessage()); logger.debug(ex.getMessage(), ex); logger.debug("Retrying request"); } retryReason = ex; } else { throw ex; } } } return response; }