@Test public void createsARequestWithDefaultValues() { HttpRequest request = get("/index").build(); assertThat(request.version(), is(HTTP_1_1)); assertThat(request.url().toString(), is("/index")); assertThat(request.path(), is("/index")); assertThat(request.id(), is(notNullValue())); assertThat(request.cookies(), is(emptyIterable())); assertThat(request.headers(), is(emptyIterable())); assertThat(request.headers("any"), is(emptyIterable())); assertThat(request.body().length, is(0)); assertThat(request.cookie("any"), isAbsent()); assertThat(request.header("any"), isAbsent()); assertThat(request.keepAlive(), is(true)); assertThat(request.method(), is(GET)); assertThat(request.queryParam("any"), isAbsent()); assertThat(request.queryParams("any"), is(emptyIterable())); }
@Test public void transformsRequest() { HttpRequest request = get("/foo") .header("remove", "remove") .build(); HttpRequest newRequest = request.newBuilder() .method(DELETE) .uri("/home") .header("remove", "notanymore") .build(); assertThat(newRequest.method(), is(DELETE)); assertThat(newRequest.url().path(), is("/home")); assertThat(newRequest.headers(), hasItem(header("remove", "notanymore"))); }
/** * Converts this request into a streaming form (HttpRequest). * * Converts this request into a HttpRequest object which represents the HTTP request as a * stream of bytes. * * @return A streaming HttpRequest object. */ public HttpRequest toStreamingRequest() { HttpRequest.Builder streamingBuilder = new HttpRequest.Builder(this) .clientAddress(clientAddress); if (this.body.length == 0) { return streamingBuilder.body(Observable.empty()).build(); } else { return streamingBuilder.body(Observable.just(Unpooled.copiedBuffer(body))).build(); } }
/** * Aggregates content stream and converts this request to a {@link HttpRequest}. * <p> * Returns a {@link Eventual} that eventually produces a * {@link HttpRequest}. The resulting full request object has the same * request line, headers, and content as this request. * <p> * The content stream is aggregated asynchronously. The stream may be connected * to a network socket or some other content producer. Once aggregated, a * HttpRequest object is emitted on the returned {@link Eventual}. * <p> * A sole {@code maxContentBytes} argument is a backstop defence against excessively * long content streams. The {@code maxContentBytes} should be set to a sensible * value according to your application requirements and heap size. When the content * size stream exceeds the {@code maxContentBytes}, a @{link ContentOverflowException} * is emitted on the returned observable. * * @param maxContentBytes maximum expected content size * @return a {@link Eventual} */ public Eventual<HttpRequest> aggregate(int maxContentBytes) { return Eventual.from( body.aggregate(maxContentBytes) .thenApply(it -> new HttpRequest.Builder(this, decodeAndRelease(it)).build()) ); }
@Test public void convertsToStreamingHttpRequest() throws Exception { HttpRequest fullRequest = new HttpRequest.Builder(POST, "/foo/bar").body("foobar", UTF_8) .version(HTTP_1_1) .header("HeaderName", "HeaderValue") .cookies(requestCookie("CookieName", "CookieValue")) .build(); LiveHttpRequest streaming = fullRequest.stream(); assertThat(streaming.method(), is(HttpMethod.POST)); assertThat(streaming.url(), is(url("/foo/bar").build())); assertThat(streaming.version(), is(HTTP_1_1)); assertThat(streaming.headers(), containsInAnyOrder( header("Content-Length", "6"), header("HeaderName", "HeaderValue"), header("Cookie", "CookieName=CookieValue"))); assertThat(streaming.cookies(), contains(requestCookie("CookieName", "CookieValue"))); StepVerifier.create(streaming.aggregate(0x10000).map(it -> it.bodyAs(UTF_8))) .expectNext("foobar") .verifyComplete(); }
/** * Sets the request body. * <p> * This method encodes the content to a byte array provided, and * sets the Content-Length header *if* the setContentLength * argument is true. * * @param content request body * @param setContentLength If true, Content-Length header is set, otherwise it is not set. * @return {@code this} */ public Builder body(byte[] content, boolean setContentLength) { this.body = content != null ? content.clone() : new byte[0]; if (setContentLength) { header(CONTENT_LENGTH, this.body.length); } return this; }
/** * Rewrites the URL of the request according to the rewrite rules. * * @param request a request * @return a rewritten request */ public HttpRequest rewrite(HttpRequest request) { String path = request.path(); String newPath = newPath(path); if (!Objects.equals(newPath, path)) { Url newUrl = request.url().newBuilder().path(newPath).build(); return request.newBuilder() .url(newUrl) .build(); } return request; }
/** * Sets the request body. * <p> * This method encodes the content to a byte array using the specified * charset, and sets the Content-Length header *if* the setContentLength * argument is true. * * @param content request body * @param charset charset used for encoding request body * @param setContentLength If true, Content-Length header is set, otherwise it is not set. * @return {@code this} */ public Builder body(String content, Charset charset, boolean setContentLength) { requireNonNull(charset, "Charset is not provided."); String sanitised = content == null ? "" : content; return body(sanitised.getBytes(charset), setContentLength); }
/** * Adds cookies into the "Cookie" header. If the name matches an already existing cookie, the value will be overwritten. * <p> * Note that this requires decoding the current header value before re-encoding, so it is most efficient to * add all new cookies in one call to the method rather than spreading them out. * * @param cookies new cookies * @return {@code this} */ public Builder addCookies(Collection<RequestCookie> cookies) { requireNonNull(cookies); Set<RequestCookie> currentCookies = decode(headers.get(COOKIE)); List<RequestCookie> newCookies = concat(cookies.stream(), currentCookies.stream()).collect(toList()); return cookies(newCookies); }
/** * Sets the cookies on this request by overwriting the value of the "Cookie" header. * * @param cookies cookies * @return {@code this} */ public Builder cookies(Collection<RequestCookie> cookies) { requireNonNull(cookies); headers.remove(COOKIE); if (!cookies.isEmpty()) { header(COOKIE, encode(cookies)); } return this; }
@Test public void requestBodyCannotBeChangedViaStreamingRequest() { HttpRequest original = HttpRequest.get("/foo") .body("original", UTF_8) .build(); Flux.from(original.stream() .body() .map(buffer -> { buffer.delegate().array()[0] = 'A'; return buffer; })) .subscribe(); assertThat(original.bodyAs(UTF_8), is("original")); }
private DecodedRequest(T content) { this.requestBuilder = newBuilder().body(content.toString()); this.content = content; }
@Test(expectedExceptions = NullPointerException.class) public void rejectsNullCookie() { get("/").cookies((RequestCookie) null); }
private void setHostHeader() { url.authority() .ifPresent(authority -> header(HOST, authority.hostAndPort())); }
@Test public void contentFromByteArraySetsContentLengthIfRequired() { HttpRequest response1 = HttpRequest.get("/") .body("Response content.".getBytes(UTF_16), true) .build(); assertThat(response1.body(), is("Response content.".getBytes(UTF_16))); assertThat(response1.header("Content-Length"), is(Optional.of("36"))); HttpRequest response2 = HttpRequest.get("/") .body("Response content.".getBytes(UTF_8), false) .build(); assertThat(response2.body(), is("Response content.".getBytes(UTF_8))); assertThat(response2.header("Content-Length"), is(Optional.empty())); }
@Test public void extractsAllCookies() { HttpRequest request = get("/") .cookies( requestCookie("cookie1", "foo"), requestCookie("cookie3", "baz"), requestCookie("cookie2", "bar")) .build(); assertThat(request.cookies(), containsInAnyOrder( requestCookie("cookie1", "foo"), requestCookie("cookie2", "bar"), requestCookie("cookie3", "baz"))); }
private void setHostHeader() { url.authority() .ifPresent(authority -> header(HOST, authority.hostAndPort())); }
/** * Sets the request body. * <p> * This method encodes a String content to a byte array using the specified * charset, and sets the Content-Length header accordingly. * * @param content request body * @param charset Charset for string encoding * @return {@code this} */ public Builder body(String content, Charset charset) { return body(content, charset, true); }