@Test public void doesntFireEventsThatNeverOccurred() { Mono<LiveHttpResponse> publisher = Mono.just(response(OK).body(new ByteStream(Flux.just(new Buffer("hey", UTF_8)))).build()); Flux<LiveHttpResponse> listener = ResponseEventListener.from(publisher) .whenCancelled(() -> cancelled.set(true)) .whenResponseError(cause -> responseError.set(cause)) .whenContentError(cause -> contentError.set(cause)) .whenCompleted(() -> completed.set(true)) .apply(); StepVerifier.create(listener) .consumeNextWith(LiveHttpMessage::consume) .then(() -> { assertFalse(cancelled.get()); assertNull(responseError.get()); assertNull(contentError.get()); assertTrue(completed.get()); }) .verifyComplete(); }
/** * Adds cookies into this response by adding "Set-Cookie" headers. * * @param cookies cookies * @return {@code this} */ public Builder addCookies(Collection<ResponseCookie> cookies) { requireNonNull(cookies); if (cookies.isEmpty()) { return this; } removeCookies(cookies.stream().map(ResponseCookie::name).collect(toList())); encode(cookies).forEach(cookie -> addHeader(SET_COOKIE, cookie)); return this; }
@Test public void transformerRemovesCookiesWithList() { LiveHttpResponse response = response() .addCookies(ImmutableList.of(responseCookie("x", "y").build())) .build() .newBuilder() .removeCookies(ImmutableList.of("x")) .build(); assertEquals(response.cookie("x"), Optional.empty()); }
/** * Builds a new full response based on the settings configured in this builder. * <p> * Validates and builds a {link LiveHttpResponse} object. Object validation can be * disabled with {@link this.disableValidation} method. * <p> * When validation is enabled (by default), ensures that: * * <li> * <ul>There is maximum of only one {@code Content-Length} header</ul> * <ul>The {@code Content-Length} header is zero or positive integer</ul> * </li> * * @return a new full response. * @throws IllegalArgumentException when validation fails */ public LiveHttpResponse build() { if (validate) { ensureContentLengthIsValid(); } return new LiveHttpResponse(this); }
@Test public void firesWhenContentCancelled() { EmitterProcessor<Buffer> contentPublisher = EmitterProcessor.create(); Flux<LiveHttpResponse> listener = ResponseEventListener.from( Flux.just(response(OK) .body(new ByteStream(contentPublisher)) .build())) .whenCancelled(() -> cancelled.set(true)) .apply(); StepVerifier.create(listener) .consumeNextWith(response -> StepVerifier.create(response.body()) .then(() -> assertFalse(cancelled.get())) .thenCancel() .verify()) .verifyComplete(); assertTrue(cancelled.get()); }
@Test public void ignoresResponseErrorAfterHeaders() { Flux<LiveHttpResponse> publisher = Flux.just( response(OK) .body(new ByteStream(Flux.just(new Buffer("hey", UTF_8)))) .build()) .concatWith(Flux.error(new RuntimeException())); Publisher<LiveHttpResponse> listener = ResponseEventListener.from(publisher) .whenCancelled(() -> cancelled.set(true)) .whenResponseError(cause -> responseError.set(cause)) .whenContentError(cause -> contentError.set(cause)) .apply(); StepVerifier.create(listener) .consumeNextWith(LiveHttpMessage::consume) .verifyError(); assertFalse(cancelled.get()); assertNull(responseError.get()); assertNull(contentError.get()); }
@Test public void transformerReplacesBody() { Buffer buf1 = new Buffer("chunk 1, ", UTF_8); Buffer buf2 = new Buffer("chunk 2.", UTF_8); LiveHttpResponse response1 = response(NO_CONTENT) .body(new ByteStream(Flux.just(buf1, buf2))) .build() .newBuilder() .body(body -> body.replaceWith(ByteStream.from("replacement", UTF_8))) .build(); HttpResponse response2 = Mono.from(response1.aggregate(100)).block(); assertEquals(response2.bodyAs(UTF_8), "replacement"); assertEquals(buf1.delegate().refCnt(), 0); assertEquals(buf2.delegate().refCnt(), 0); }
@Test public void encodesToFullHttpResponse() { LiveHttpResponse response = response(CREATED) .version(HTTP_1_0) .header("HeaderName", "HeaderValue") .cookies(responseCookie("CookieName", "CookieValue").build()) .body(new ByteStream(Flux.just("foo", "bar").map(it -> new Buffer(copiedBuffer(it, UTF_8))))) .build(); HttpResponse full = Mono.from(response.aggregate(0x1000)).block(); assertThat(full.status(), is(CREATED)); assertThat(full.version(), is(HTTP_1_0)); assertThat(full.headers(), containsInAnyOrder(header("HeaderName", "HeaderValue"), header("Set-Cookie", "CookieName=CookieValue"))); assertThat(full.cookies(), contains(responseCookie("CookieName", "CookieValue").build())); assertThat(full.body(), is(bytes("foobar"))); }
/** * Converts this response to a streaming form (LiveHttpResponse). * <p> * Converts this response to an LiveHttpResponse object which represents the HTTP response as a * stream of bytes. * * @return A streaming LiveHttpResponse object */ public LiveHttpResponse stream() { if (this.body.length == 0) { return new LiveHttpResponse.Builder(this, new ByteStream(Flux.empty())).build(); } else { return new LiveHttpResponse.Builder(this, new ByteStream(Flux.just(new Buffer(copiedBuffer(this.body))))).build(); } }
@Test public void firesResponseContentError() { Mono<LiveHttpResponse> publisher = Mono.just( response(OK) .body(new ByteStream(Flux.error(new RuntimeException()))) .build()); Publisher<LiveHttpResponse> listener = ResponseEventListener.from(publisher) .whenContentError(cause -> responseError.set(cause)) .apply(); StepVerifier.create(listener) .consumeNextWith(LiveHttpMessage::consume) .verifyComplete(); assertTrue(responseError.get() instanceof RuntimeException); }
private LiveHttpResponse exceptionToResponse(Throwable exception, LiveHttpRequest request) { HttpResponseStatus status = status(exception instanceof PluginException ? exception.getCause() : exception); String message = status.code() >= 500 ? "Site temporarily unavailable." : status.description(); return responseEnhancer.enhance( LiveHttpResponse .response(status) .body(new ByteStream(Flux.just(new Buffer(message, UTF_8)))) .build() .newBuilder(), request) .header(CONTENT_LENGTH, message.getBytes(UTF_8).length) .build(); }
@Test(dataProvider = "responses") public void shouldCheckIfCurrentResponseIsARedirectToOtherResource(HttpResponseStatus status, boolean isRedirect) { assertThat(response(status).build().isRedirect(), is(isRedirect)); }
public Transformer(LiveHttpResponse response) { this.builder = new Builder(response); }
@Test public void transformsBody() throws ExecutionException, InterruptedException { Buffer buffer = new Buffer("I'm going to get removed.", UTF_8); LiveHttpResponse response = response(NO_CONTENT) .body(new ByteStream(Flux.just(buffer))) .build(); HttpResponse fullResponse = Mono.from(response.newBuilder() .body(ByteStream::drop) .build() .aggregate(1000)).block(); assertThat(fullResponse.body().length, is(0)); assertThat(buffer.delegate().refCnt(), is(0)); }
@Test public void createsANonCacheableResponse() { assertThat(response().disableCaching().build().headers(), is(isNotCacheable())); }
@Override public LiveHttpResponse build() { return this.builder.build(); } }