@SuppressWarnings({ "unchecked", "rawtypes" }) public void testTooLargeResponse() throws Exception { ContentTooLongException tooLong = new ContentTooLongException("too long!"); CloseableHttpAsyncClient httpClient = mock(CloseableHttpAsyncClient.class); when(httpClient.<HttpResponse>execute(any(HttpAsyncRequestProducer.class), any(HttpAsyncResponseConsumer.class), any(HttpClientContext.class), any(FutureCallback.class))).then(new Answer<Future<HttpResponse>>() { @Override public Future<HttpResponse> answer(InvocationOnMock invocationOnMock) throws Throwable { HeapBufferedAsyncResponseConsumer consumer = (HeapBufferedAsyncResponseConsumer) invocationOnMock.getArguments()[1]; FutureCallback callback = (FutureCallback) invocationOnMock.getArguments()[3]; assertEquals(new ByteSizeValue(100, ByteSizeUnit.MB).bytesAsInt(), consumer.getBufferLimit()); callback.failed(tooLong); return null; } }); RemoteScrollableHitSource source = sourceWithMockedClient(true, httpClient); AtomicBoolean called = new AtomicBoolean(); Consumer<Response> checkResponse = r -> called.set(true); Throwable e = expectThrows(RuntimeException.class, () -> source.doStartNextScroll(FAKE_SCROLL_ID, timeValueMillis(0), checkResponse)); // Unwrap the some artifacts from the test while (e.getMessage().equals("failed")) { e = e.getCause(); } // This next exception is what the user sees assertEquals("Remote responded with a chunk that was too large. Use a smaller batch size.", e.getMessage()); // And that exception is reported as being caused by the underlying exception returned by the client assertSame(tooLong, e.getCause()); assertFalse(called.get()); }
private static void bufferLimitTest(HeapBufferedAsyncResponseConsumer consumer, int bufferLimit) throws Exception { ProtocolVersion protocolVersion = new ProtocolVersion("HTTP", 1, 1); StatusLine statusLine = new BasicStatusLine(protocolVersion, 200, "OK"); consumer.onResponseReceived(new BasicHttpResponse(statusLine)); final AtomicReference<Long> contentLength = new AtomicReference<>(); HttpEntity entity = new StringEntity("", ContentType.APPLICATION_JSON) { @Override public long getContentLength() { return contentLength.get(); } }; contentLength.set(randomLong(bufferLimit)); consumer.onEntityEnclosed(entity, ContentType.APPLICATION_JSON); contentLength.set(randomLongBetween(bufferLimit + 1, MAX_TEST_BUFFER_SIZE)); try { consumer.onEntityEnclosed(entity, ContentType.APPLICATION_JSON); } catch(ContentTooLongException e) { assertEquals("entity content is too long [" + entity.getContentLength() + "] for the configured buffer limit [" + bufferLimit + "]", e.getMessage()); } }
@Override protected void onEntityEnclosed(HttpEntity entity, ContentType contentType) throws IOException { long len = entity.getContentLength(); if (len > bufferLimitBytes) { throw new ContentTooLongException("entity content is too long [" + len + "] for the configured buffer limit [" + bufferLimitBytes + "]"); } if (len < 0) { len = 4096; } this.buf = new SimpleInputBuffer((int) len, getByteBufferAllocator()); this.response.setEntity(new ContentBufferEntity(entity, this.buf)); }
@Override public InputStream getContent() throws IOException { if (this.getContentLength() < 0) { throw new ContentTooLongException("Content length is unknown"); } // else if (this.contentLength > 25 * 1024) { // throw new ContentTooLongException("Content length is too long: " + this.contentLength); // } final ByteArrayOutputStream outstream = new ByteArrayOutputStream(); writeTo(outstream); outstream.flush(); return new ByteArrayInputStream(outstream.toByteArray()); }
@Override protected void onEntityEnclosed(final HttpEntity entity, final ContentType contentType) throws IOException { long len = entity.getContentLength(); if (len > Integer.MAX_VALUE) { throw new ContentTooLongException("Entity content is too long: " + len); } if (len < 0) { len = BUFFER_SIZE; } this.buf = new SimpleInputBuffer((int) len, new HeapByteBufferAllocator()); this.httpResponse.setEntity(new ContentBufferEntity(entity, this.buf)); }
@Override public InputStream getContent() throws IOException { if (this.contentLength < 0) { throw new ContentTooLongException("Content length is unknown"); } else if (this.contentLength > 25 * 1024) { throw new ContentTooLongException("Content length is too long: " + this.contentLength); } final ByteArrayOutputStream outstream = new ByteArrayOutputStream(); writeTo(outstream); outstream.flush(); return new ByteArrayInputStream(outstream.toByteArray()); }
@Override protected void onEntityEnclosed(final HttpEntity entity, final ContentType contentType) throws IOException { long len = entity.getContentLength(); if (len > Integer.MAX_VALUE) { throw new ContentTooLongException("Entity content is too long: " + len); } if (len < 0) { len = 4096; } this.buf = new SimpleInputBuffer((int) len, new HeapByteBufferAllocator()); this.response.setEntity(new ContentBufferEntity(entity, this.buf)); }