From 7381276e950159bcf76c492c9e7e0245c4ce3504 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Wed, 19 Aug 2026 19:18:59 +0200 Subject: [PATCH] HttpClient Getting started guide --- samples/pom.xml | 7 + .../AsyncHttpClientBootstrapExample.java | 96 +++++ .../AsyncHttpClientContextExample.java | 117 ++++++ .../http/examples/AsyncQuickStart.java | 147 -------- .../ClassicHttpClientBootstrapExample.java | 86 +++++ .../ClassicHttpClientContextExample.java | 108 ++++++ .../ClassicHttpClientOpenResponseExample.java | 86 +++++ .../hc/client5/http/examples/QuickStart.java | 78 ---- .../examples/fluent/FluentQuickStart.java | 45 --- .../http/client/fluent/FluentQuickStart.java | 42 --- .../http/examples/client/QuickStart.java | 88 ----- .../getting-started.md | 357 ++++++++++++++++++ .../httpcomponents-client-5.7.x/index.md | 63 ++-- 13 files changed, 897 insertions(+), 423 deletions(-) create mode 100644 samples/src/main/java/org/apache/hc/client5/http/examples/AsyncHttpClientBootstrapExample.java create mode 100644 samples/src/main/java/org/apache/hc/client5/http/examples/AsyncHttpClientContextExample.java delete mode 100644 samples/src/main/java/org/apache/hc/client5/http/examples/AsyncQuickStart.java create mode 100644 samples/src/main/java/org/apache/hc/client5/http/examples/ClassicHttpClientBootstrapExample.java create mode 100644 samples/src/main/java/org/apache/hc/client5/http/examples/ClassicHttpClientContextExample.java create mode 100644 samples/src/main/java/org/apache/hc/client5/http/examples/ClassicHttpClientOpenResponseExample.java delete mode 100644 samples/src/main/java/org/apache/hc/client5/http/examples/QuickStart.java delete mode 100644 samples/src/main/java/org/apache/hc/client5/http/examples/fluent/FluentQuickStart.java delete mode 100644 samples/src/main/java/org/apache/http/client/fluent/FluentQuickStart.java delete mode 100644 samples/src/main/java/org/apache/http/examples/client/QuickStart.java create mode 100644 src/site/markdown/httpcomponents-client-5.7.x/getting-started.md diff --git a/samples/pom.xml b/samples/pom.xml index 3930d36..871146f 100644 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -41,6 +41,7 @@ 4.5.14 5.5-beta1 5.6.1 + 1.7.36 @@ -74,6 +75,12 @@ httpclient5-fluent ${hc5.client.version} + + org.slf4j + slf4j-jdk14 + ${slf4j.version} + runtime + diff --git a/samples/src/main/java/org/apache/hc/client5/http/examples/AsyncHttpClientBootstrapExample.java b/samples/src/main/java/org/apache/hc/client5/http/examples/AsyncHttpClientBootstrapExample.java new file mode 100644 index 0000000..1847136 --- /dev/null +++ b/samples/src/main/java/org/apache/hc/client5/http/examples/AsyncHttpClientBootstrapExample.java @@ -0,0 +1,96 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.client5.http.examples; + +import java.util.concurrent.Future; + +import org.apache.hc.client5.http.HttpRoute; +import org.apache.hc.client5.http.config.ConnectionConfig; +import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; +import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder; +import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager; +import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.HttpRequest; +import org.apache.hc.core5.http.HttpResponse; +import org.apache.hc.core5.http.Message; +import org.apache.hc.core5.http.nio.entity.StringAsyncEntityConsumer; +import org.apache.hc.core5.http.nio.support.BasicRequestProducer; +import org.apache.hc.core5.http.nio.support.BasicResponseConsumer; +import org.apache.hc.core5.http.support.BasicRequestBuilder; +import org.apache.hc.core5.pool.ConnPoolControl; +import org.apache.hc.core5.util.TimeValue; + + +public class AsyncHttpClientBootstrapExample { + + final static PoolingAsyncClientConnectionManager CONN_MANAGER; + final static CloseableHttpAsyncClient CLIENT; + + static { + CONN_MANAGER = PoolingAsyncClientConnectionManagerBuilder.create() + .setDefaultConnectionConfig(ConnectionConfig.custom() + .setTimeToLive(TimeValue.ofMinutes(5)) + .build()) + .build(); + } + + static { + CLIENT = HttpAsyncClientBuilder.create() + .setConnectionManager(CONN_MANAGER) + .build(); + CLIENT.start(); + } + + static CloseableHttpAsyncClient getClient() { + return CLIENT; + } + + static ConnPoolControl getConnPool() { + return CONN_MANAGER; + } + + public static void main(final String[] args) throws Exception { + final CloseableHttpAsyncClient client = getClient(); + final HttpRequest httpGet = BasicRequestBuilder.get() + .setHttpHost(new HttpHost("http", "httpbin.org")) + .setPath("/get") + .build(); + final Future> future = client.execute( + new BasicRequestProducer(httpGet, null), + new BasicResponseConsumer<>(StringAsyncEntityConsumer::new), + null); + final Message response = future.get(); + System.out.println(response.head().getCode()); + System.out.println(response.body()); + + final ConnPoolControl connPool = getConnPool(); + connPool.closeIdle(TimeValue.ZERO_MILLISECONDS); + } + +} diff --git a/samples/src/main/java/org/apache/hc/client5/http/examples/AsyncHttpClientContextExample.java b/samples/src/main/java/org/apache/hc/client5/http/examples/AsyncHttpClientContextExample.java new file mode 100644 index 0000000..0997c18 --- /dev/null +++ b/samples/src/main/java/org/apache/hc/client5/http/examples/AsyncHttpClientContextExample.java @@ -0,0 +1,117 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.client5.http.examples; + +import java.util.concurrent.Future; + +import org.apache.hc.client5.http.ContextBuilder; +import org.apache.hc.client5.http.HttpRoute; +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.cookie.BasicCookieStore; +import org.apache.hc.client5.http.cookie.Cookie; +import org.apache.hc.client5.http.cookie.CookieStore; +import org.apache.hc.client5.http.cookie.StandardCookieSpec; +import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; +import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder; +import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager; +import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; +import org.apache.hc.client5.http.protocol.HttpClientContext; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.HttpRequest; +import org.apache.hc.core5.http.HttpResponse; +import org.apache.hc.core5.http.Message; +import org.apache.hc.core5.http.nio.entity.StringAsyncEntityConsumer; +import org.apache.hc.core5.http.nio.support.BasicRequestProducer; +import org.apache.hc.core5.http.nio.support.BasicResponseConsumer; +import org.apache.hc.core5.http.support.BasicRequestBuilder; +import org.apache.hc.core5.pool.ConnPoolControl; + + +public class AsyncHttpClientContextExample { + + final static PoolingAsyncClientConnectionManager CONN_MANAGER; + final static CloseableHttpAsyncClient CLIENT; + + static { + CONN_MANAGER = PoolingAsyncClientConnectionManagerBuilder.create() + .build(); + } + + static { + CLIENT = HttpAsyncClientBuilder.create() + .setConnectionManager(CONN_MANAGER) + .build(); + CLIENT.start(); + } + + static CloseableHttpAsyncClient getClient() { + return CLIENT; + } + + static ConnPoolControl getConnPool() { + return CONN_MANAGER; + } + + public static void main(final String[] args) throws Exception { + final CloseableHttpAsyncClient client = getClient(); + + // Create a local instance of cookie store + final CookieStore cookieStore = new BasicCookieStore(); + + // Create local HTTP context + final HttpClientContext localContext = ContextBuilder.create() + // Bind custom cookie store to the local context + .useCookieStore(cookieStore) + .build(); + // Provide request custom settings + localContext.setRequestConfig(RequestConfig.custom() + .setCookieSpec(StandardCookieSpec.STRICT) + .build()); + + for (int i = 1; i <= 3; i++) { + final HttpRequest httpGet = BasicRequestBuilder.get() + .setHttpHost(new HttpHost("http", "httpbin.org")) + .setPath("/cookies") + .build(); + final Future> future = client.execute( + new BasicRequestProducer(httpGet, null), + new BasicResponseConsumer<>(StringAsyncEntityConsumer::new), + null, + localContext, + null); + final Message response = future.get(); + System.out.println(response.head().getCode()); + System.out.println(response.body()); + + for (Cookie cookie : cookieStore.getCookies()) { + System.out.println("Local cookie: " + cookie); + } + } + } + +} diff --git a/samples/src/main/java/org/apache/hc/client5/http/examples/AsyncQuickStart.java b/samples/src/main/java/org/apache/hc/client5/http/examples/AsyncQuickStart.java deleted file mode 100644 index af2ca7a..0000000 --- a/samples/src/main/java/org/apache/hc/client5/http/examples/AsyncQuickStart.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - * - */ - -package org.apache.hc.client5.http.examples; - -import java.io.IOException; -import java.nio.CharBuffer; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Future; - -import org.apache.hc.client5.http.async.methods.AbstractCharResponseConsumer; -import org.apache.hc.client5.http.async.methods.SimpleHttpRequest; -import org.apache.hc.client5.http.async.methods.SimpleHttpResponse; -import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder; -import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; -import org.apache.hc.client5.http.impl.async.HttpAsyncClients; -import org.apache.hc.core5.concurrent.FutureCallback; -import org.apache.hc.core5.http.ContentType; -import org.apache.hc.core5.http.HttpException; -import org.apache.hc.core5.http.HttpResponse; -import org.apache.hc.core5.http.nio.AsyncRequestProducer; -import org.apache.hc.core5.http.nio.support.AsyncRequestBuilder; - -public class AsyncQuickStart { - - public static void main (final String[] args) throws Exception { - try (final CloseableHttpAsyncClient httpclient = HttpAsyncClients.createDefault()) { - // Start the client - httpclient.start(); - - // Execute request - final SimpleHttpRequest request1 = SimpleRequestBuilder.get("http://httpbin.org/get").build(); - final Future future = httpclient.execute(request1, null); - // and wait until response is received - final SimpleHttpResponse response1 = future.get(); - System.out.println(request1.getRequestUri() + "->" + response1.getCode()); - - // One most likely would want to use a callback for operation result - final CountDownLatch latch1 = new CountDownLatch(1); - final SimpleHttpRequest request2 = SimpleRequestBuilder.get("http://httpbin.org/get").build(); - httpclient.execute(request2, new FutureCallback() { - - @Override - public void completed(final SimpleHttpResponse response2) { - latch1.countDown(); - System.out.println(request2.getRequestUri() + "->" + response2.getCode()); - } - - @Override - public void failed(final Exception ex) { - latch1.countDown(); - System.out.println(request2.getRequestUri() + "->" + ex); - } - - @Override - public void cancelled() { - latch1.countDown(); - System.out.println(request2.getRequestUri() + " cancelled"); - } - - }); - latch1.await(); - - // In real world one most likely would want also want to stream - // request and response body content - final CountDownLatch latch2 = new CountDownLatch(1); - final AsyncRequestProducer producer3 = AsyncRequestBuilder.get("http://httpbin.org/get").build(); - final AbstractCharResponseConsumer consumer3 = new AbstractCharResponseConsumer() { - - HttpResponse response; - - @Override - protected void start(final HttpResponse response, final ContentType contentType) throws HttpException, IOException { - this.response = response; - } - - @Override - protected int capacityIncrement() { - return Integer.MAX_VALUE; - } - - @Override - protected void data(final CharBuffer data, final boolean endOfStream) throws IOException { - // Do something useful - } - - @Override - protected HttpResponse buildResult() throws IOException { - return response; - } - - @Override - public void releaseResources() { - } - - }; - httpclient.execute(producer3, consumer3, new FutureCallback() { - - @Override - public void completed(final HttpResponse response3) { - latch2.countDown(); - System.out.println(request2.getRequestUri() + "->" + response3.getCode()); - } - - @Override - public void failed(final Exception ex) { - latch2.countDown(); - System.out.println(request2.getRequestUri() + "->" + ex); - } - - @Override - public void cancelled() { - latch2.countDown(); - System.out.println(request2.getRequestUri() + " cancelled"); - } - - }); - latch2.await(); - - } - } - -} diff --git a/samples/src/main/java/org/apache/hc/client5/http/examples/ClassicHttpClientBootstrapExample.java b/samples/src/main/java/org/apache/hc/client5/http/examples/ClassicHttpClientBootstrapExample.java new file mode 100644 index 0000000..ba4f681 --- /dev/null +++ b/samples/src/main/java/org/apache/hc/client5/http/examples/ClassicHttpClientBootstrapExample.java @@ -0,0 +1,86 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.hc.client5.http.examples; + +import org.apache.hc.client5.http.HttpRoute; +import org.apache.hc.client5.http.config.ConnectionConfig; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder; +import org.apache.hc.core5.http.ClassicHttpRequest; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.HttpResponse; +import org.apache.hc.core5.http.Message; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.apache.hc.core5.http.io.support.ClassicRequestBuilder; +import org.apache.hc.core5.pool.ConnPoolControl; +import org.apache.hc.core5.util.TimeValue; + +public class ClassicHttpClientBootstrapExample { + + final static PoolingHttpClientConnectionManager CONN_MANAGER; + final static CloseableHttpClient CLIENT; + + static { + CONN_MANAGER = PoolingHttpClientConnectionManagerBuilder.create() + .setDefaultConnectionConfig(ConnectionConfig.custom() + .setTimeToLive(TimeValue.ofMinutes(5)) + .build()) + .build(); + } + + static { + CLIENT = HttpClientBuilder.create() + .setConnectionManager(CONN_MANAGER) + .build(); + } + + static CloseableHttpClient getClient() { + return CLIENT; + } + + static ConnPoolControl getConnPool() { + return CONN_MANAGER; + } + + public static void main(final String[] args) throws Exception { + final CloseableHttpClient client = getClient(); + final ClassicHttpRequest httpGet = ClassicRequestBuilder.get() + .setHttpHost(new HttpHost("http", "httpbin.org")) + .setPath("/get") + .build(); + final Message response = client.execute(httpGet, r -> + new Message<>(r, EntityUtils.toString(r.getEntity()))); + System.out.println(response.head().getCode()); + System.out.println(response.body()); + + final ConnPoolControl connPool = getConnPool(); + connPool.closeIdle(TimeValue.ZERO_MILLISECONDS); + } + +} diff --git a/samples/src/main/java/org/apache/hc/client5/http/examples/ClassicHttpClientContextExample.java b/samples/src/main/java/org/apache/hc/client5/http/examples/ClassicHttpClientContextExample.java new file mode 100644 index 0000000..bf2f3ae --- /dev/null +++ b/samples/src/main/java/org/apache/hc/client5/http/examples/ClassicHttpClientContextExample.java @@ -0,0 +1,108 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.client5.http.examples; + +import org.apache.hc.client5.http.ContextBuilder; +import org.apache.hc.client5.http.HttpRoute; +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.cookie.BasicCookieStore; +import org.apache.hc.client5.http.cookie.Cookie; +import org.apache.hc.client5.http.cookie.CookieStore; +import org.apache.hc.client5.http.cookie.StandardCookieSpec; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder; +import org.apache.hc.client5.http.protocol.HttpClientContext; +import org.apache.hc.core5.http.ClassicHttpRequest; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.HttpResponse; +import org.apache.hc.core5.http.Message; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.apache.hc.core5.http.io.support.ClassicRequestBuilder; +import org.apache.hc.core5.pool.ConnPoolControl; + +public class ClassicHttpClientContextExample { + + final static PoolingHttpClientConnectionManager CONN_MANAGER; + final static CloseableHttpClient CLIENT; + + static { + CONN_MANAGER = PoolingHttpClientConnectionManagerBuilder.create() + .build(); + } + + static { + CLIENT = HttpClientBuilder.create() + .setConnectionManager(CONN_MANAGER) + .build(); + } + + static CloseableHttpClient getClient() { + return CLIENT; + } + + static ConnPoolControl getConnPool() { + return CONN_MANAGER; + } + + public static void main(final String[] args) throws Exception { + final CloseableHttpClient client = getClient(); + + // Create a local instance of cookie store + final CookieStore cookieStore = new BasicCookieStore(); + + // Create local HTTP context + final HttpClientContext localContext = ContextBuilder.create() + // Bind custom cookie store to the local context + .useCookieStore(cookieStore) + .build(); + // Provide request custom settings + localContext.setRequestConfig(RequestConfig.custom() + .setCookieSpec(StandardCookieSpec.STRICT) + .build()); + + for (int i = 1; i <= 3; i++) { + final ClassicHttpRequest httpGet = ClassicRequestBuilder.get() + .setHttpHost(new HttpHost("http", "httpbin.org")) + .setPath("/cookies") + .build(); + final Message response = client.execute( + httpGet, localContext, r -> + new Message<>(r, EntityUtils.toString(r.getEntity()))); + System.out.println(response.head().getCode()); + System.out.println(response.body()); + + for (Cookie cookie : cookieStore.getCookies()) { + System.out.println("Local cookie: " + cookie); + } + } + } + +} + diff --git a/samples/src/main/java/org/apache/hc/client5/http/examples/ClassicHttpClientOpenResponseExample.java b/samples/src/main/java/org/apache/hc/client5/http/examples/ClassicHttpClientOpenResponseExample.java new file mode 100644 index 0000000..dc9ad35 --- /dev/null +++ b/samples/src/main/java/org/apache/hc/client5/http/examples/ClassicHttpClientOpenResponseExample.java @@ -0,0 +1,86 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.hc.client5.http.examples; + +import org.apache.hc.client5.http.HttpRoute; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder; +import org.apache.hc.client5.http.protocol.HttpClientContext; +import org.apache.hc.core5.http.ClassicHttpRequest; +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.apache.hc.core5.http.io.support.ClassicRequestBuilder; +import org.apache.hc.core5.pool.ConnPoolControl; +import org.apache.hc.core5.util.TimeValue; + +public class ClassicHttpClientOpenResponseExample { + + final static PoolingHttpClientConnectionManager CONN_MANAGER; + final static CloseableHttpClient CLIENT; + + static { + CONN_MANAGER = PoolingHttpClientConnectionManagerBuilder.create() + .build(); + } + + static { + CLIENT = HttpClientBuilder.create() + .setConnectionManager(CONN_MANAGER) + .build(); + } + + static CloseableHttpClient getClient() { + return CLIENT; + } + + static ConnPoolControl getConnPool() { + return CONN_MANAGER; + } + + public static void main(final String[] args) throws Exception { + final CloseableHttpClient client = getClient(); + final HttpHost target = new HttpHost("http", "httpbin.org"); + + final ClassicHttpRequest httpGet = ClassicRequestBuilder.get() + .setHttpHost(target) + .setPath("/get") + .build(); + + final HttpClientContext clientContext = HttpClientContext.create(); + try (final ClassicHttpResponse response = client.executeOpen(target, httpGet, clientContext)) { + System.out.println(response.getCode()); + System.out.println(EntityUtils.toString(response.getEntity())); + } + + final ConnPoolControl connPool = getConnPool(); + connPool.closeIdle(TimeValue.ZERO_MILLISECONDS); + } + +} diff --git a/samples/src/main/java/org/apache/hc/client5/http/examples/QuickStart.java b/samples/src/main/java/org/apache/hc/client5/http/examples/QuickStart.java deleted file mode 100644 index 4cdb59c..0000000 --- a/samples/src/main/java/org/apache/hc/client5/http/examples/QuickStart.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - * - */ -package org.apache.hc.client5.http.examples; - -import java.util.Arrays; - -import org.apache.hc.client5.http.entity.UrlEncodedFormEntity; -import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; -import org.apache.hc.client5.http.impl.classic.HttpClients; -import org.apache.hc.core5.http.ClassicHttpRequest; -import org.apache.hc.core5.http.HttpEntity; -import org.apache.hc.core5.http.io.entity.EntityUtils; -import org.apache.hc.core5.http.io.support.ClassicRequestBuilder; -import org.apache.hc.core5.http.message.BasicNameValuePair; - -public class QuickStart { - - public static void main(final String[] args) throws Exception { - try (final CloseableHttpClient httpclient = HttpClients.createDefault()) { - final ClassicHttpRequest httpGet = ClassicRequestBuilder.get("http://httpbin.org/get") - .build(); - // The underlying HTTP connection is still held by the response object - // to allow the response content to be streamed directly from the network socket. - // In order to ensure correct deallocation of system resources - // the user MUST call CloseableHttpResponse#close() from a finally clause. - // Please note that if response content is not fully consumed the underlying - // connection cannot be safely re-used and will be shut down and discarded - // by the connection manager. - httpclient.execute(httpGet, response -> { - System.out.println(response.getCode() + " " + response.getReasonPhrase()); - final HttpEntity entity1 = response.getEntity(); - // do something useful with the response body - // and ensure it is fully consumed - EntityUtils.consume(entity1); - return null; - }); - - final ClassicHttpRequest httpPost = ClassicRequestBuilder.post("http://httpbin.org/post") - .setEntity(new UrlEncodedFormEntity(Arrays.asList( - new BasicNameValuePair("username", "vip"), - new BasicNameValuePair("password", "secret")))) - .build(); - httpclient.execute(httpPost, response -> { - System.out.println(response.getCode() + " " + response.getReasonPhrase()); - final HttpEntity entity2 = response.getEntity(); - // do something useful with the response body - // and ensure it is fully consumed - EntityUtils.consume(entity2); - return null; - }); - } - } - -} diff --git a/samples/src/main/java/org/apache/hc/client5/http/examples/fluent/FluentQuickStart.java b/samples/src/main/java/org/apache/hc/client5/http/examples/fluent/FluentQuickStart.java deleted file mode 100644 index aaa52c8..0000000 --- a/samples/src/main/java/org/apache/hc/client5/http/examples/fluent/FluentQuickStart.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - * - */ -package org.apache.hc.client5.http.examples.fluent; - -import org.apache.hc.client5.http.fluent.Form; -import org.apache.hc.client5.http.fluent.Request; - -public class FluentQuickStart { - - public static void main(final String... args) throws Exception { - // The fluent API relieves the user from having to deal with manual - // deallocation of system resources at the cost of having to buffer - // response content in memory in some cases. - - Request.get("http://targethost/homepage") - .execute().returnContent(); - Request.post("http://targethost/login") - .bodyForm(Form.form().add("username", "vip").add("password", "secret").build()) - .execute().returnContent(); - } -} diff --git a/samples/src/main/java/org/apache/http/client/fluent/FluentQuickStart.java b/samples/src/main/java/org/apache/http/client/fluent/FluentQuickStart.java deleted file mode 100644 index 9e273a7..0000000 --- a/samples/src/main/java/org/apache/http/client/fluent/FluentQuickStart.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - * - */ -package org.apache.http.client.fluent; - -public class FluentQuickStart { - - public static void main(String[] args) throws Exception { - // The fluent API relieves the user from having to deal with manual - // deallocation of system resources at the cost of having to buffer - // response content in memory in some cases. - - Request.Get("http://targethost/homepage") - .execute().returnContent(); - Request.Post("http://targethost/login") - .bodyForm(Form.form().add("username", "vip").add("password", "secret").build()) - .execute().returnContent(); - } -} diff --git a/samples/src/main/java/org/apache/http/examples/client/QuickStart.java b/samples/src/main/java/org/apache/http/examples/client/QuickStart.java deleted file mode 100644 index cf5fed1..0000000 --- a/samples/src/main/java/org/apache/http/examples/client/QuickStart.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - * - */ -package org.apache.http.examples.client; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.http.HttpEntity; -import org.apache.http.NameValuePair; -import org.apache.http.client.entity.UrlEncodedFormEntity; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.message.BasicNameValuePair; -import org.apache.http.util.EntityUtils; - -public class QuickStart { - - public static void main(String[] args) throws Exception { - CloseableHttpClient httpclient = HttpClients.createDefault(); - try { - HttpGet httpGet = new HttpGet("http://httpbin.org/get"); - CloseableHttpResponse response1 = httpclient.execute(httpGet); - // The underlying HTTP connection is still held by the response object - // to allow the response content to be streamed directly from the network socket. - // In order to ensure correct deallocation of system resources - // the user MUST call CloseableHttpResponse#close() from a finally clause. - // Please note that if response content is not fully consumed the underlying - // connection cannot be safely re-used and will be shut down and discarded - // by the connection manager. - try { - System.out.println(response1.getStatusLine()); - HttpEntity entity1 = response1.getEntity(); - // do something useful with the response body - // and ensure it is fully consumed - EntityUtils.consume(entity1); - } finally { - response1.close(); - } - - HttpPost httpPost = new HttpPost("http://httpbin.org/post"); - List nvps = new ArrayList (); - nvps.add(new BasicNameValuePair("username", "vip")); - nvps.add(new BasicNameValuePair("password", "secret")); - httpPost.setEntity(new UrlEncodedFormEntity(nvps)); - CloseableHttpResponse response2 = httpclient.execute(httpPost); - - try { - System.out.println(response2.getStatusLine()); - HttpEntity entity2 = response2.getEntity(); - // do something useful with the response body - // and ensure it is fully consumed - EntityUtils.consume(entity2); - } finally { - response2.close(); - } - } finally { - httpclient.close(); - } - } - -} diff --git a/src/site/markdown/httpcomponents-client-5.7.x/getting-started.md b/src/site/markdown/httpcomponents-client-5.7.x/getting-started.md new file mode 100644 index 0000000..c27daa3 --- /dev/null +++ b/src/site/markdown/httpcomponents-client-5.7.x/getting-started.md @@ -0,0 +1,357 @@ +Getting started with HttpClient +================= + +Supported I/O models and HTTP protocol versions +------------------ + +HttpCore, the transport library HttpClient is based upon, supports two i/o models: +the classic i/o model based on blocking InputStream / OutputStream APIs and +the event-driven async i/o model. Both models have their advantages and their special +use cases. + +Ultimately, the choice of an i/o model boils down to whether or not an application can +make an effective use of message exchange multiplexing with multiple long message streams +running concurrently over the same physical connection. If so, one would be better off +choosing the async (event-driven) model. Otherwise, one may choose the classic i/o model +as in many common use cases HTTP/2 provides no tangible advantage over HTTP/1.1, +especially if the application is based on a request / response style of communicaton. + +For more details regarding the i/o modes supported by HttpCore please see +[HttpCore Getting Started Guide](../httpcomponents-core-5.5.x/getting-started.html) + +HttpClient implementations +------------------ + +HttpClient comes with several HTTP client implementations based on different i/o models +and with different set of supported features. + +* **Classic HttpClient**. This is a full-featured, general-purpose HttpClient + implementation based on the classic i/o model. This implementation should be the default + choice for the majority of users. +* **Async HttpClient**. This is a full-featured, general-purpose HttpClient implementation + based on the event-driven i/o model. This implementation supports message exchange + multiplexing over HTTP/2 connections. +* **Async HTTP/2 HttpClient**. This is a full-featured HttpClient implementation based on + the event-driven i/o model. This implementation is optimized for message exchange + multiplexing but it does not support the HTTP/1.1 protocol. +* **Minimal HttpClient**. There are several minimal HttpClient implementations based + the classic and the event-driven models optimized for efficiently of message exchange + execution with some advanced features such as automatic authentication, redirect + handling, state management and automatic content decompression removed from the + protocol pipeline. +* **Reactive Bindings**. This is a facade that acts a compatibility layer with + [Reactive Streams Bindings](https://www.reactive-streams.org/) on top of the Async + HttpClient. +* **Jakarta REST Bindings**. This is a facade that generates a dynamic proxy around an + interface with Jakarta REST annotations backed by Async HttpClient. + +The choice of an HttpClient implementation should be driven by the specific application +requirements but the classic HttpClient is likely the most reasonable option to get +started with. If the application can benefit from the message exchange multiplexing, one +can migrate from the classic implementation to Async HttpClient or Async HTTP/2 +HttpClient as described in the +[Migration Guide](../httpcomponents-client-5.6.x/migration-guide/migration-to-async-simple.html) + +For applications designed around REST communication the +[Jakarta REST Bindings](rest-client.md) may be a good choice. + +HttpClient life-cycle +------------------ + +There are several builder classes provided by the framework that facilitate the process +of HttpClient configuration and instantiation. HttpClient instances are very expensive +to create. Usually one should always re-use HttpClient for subsequent message exchanges. +Creating a new instance of HttpClient for each message exchange is like opening and +closing the browser for each and every link. It is very resource inefficient and wasteful. + +It is strongly recommended to create a single instance of HttpClient per distinct service +or application layer. The client singleton should be created and closed at the same time +with its service or application layer. + +* Classic HttpClient + +```java +final static PoolingHttpClientConnectionManager CONN_MANAGER; +final static CloseableHttpClient CLIENT; + +static { + CONN_MANAGER = PoolingHttpClientConnectionManagerBuilder.create() + .build(); +} + +static { + CLIENT = HttpClientBuilder.create() + .setConnectionManager(CONN_MANAGER) + .build(); +} + +static CloseableHttpClient getClient() { + return CLIENT; +} + +static ConnPoolControl getConnPool() { + return CONN_MANAGER; +} +``` + +* Async HttpClient + +```java +final static PoolingAsyncClientConnectionManager CONN_MANAGER; + +static { + CONN_MANAGER = PoolingAsyncClientConnectionManagerBuilder.create() + .build(); +} + +final static CloseableHttpAsyncClient CLIENT; + +static { + CLIENT = HttpAsyncClientBuilder.create() + .setConnectionManager(CONN_MANAGER) + .build(); + CLIENT.start(); +} + +static CloseableHttpAsyncClient getClient() { + return CLIENT; +} + +static ConnPoolControl getConnPool() { + return CONN_MANAGER; +} +``` +Please note that Connection manager and HttpClient instances are made static for +simplicity. One should be using an application container to manage service singletons. + +HttpClient and Connection manager instances are fully thread-safe. + +Request execution +------------------ + +HttpClient ships with several classes that represent standard HTTP methods such as `GET`, +`POST`, `HEAD`, `PUT`, `DELETE`, `QUERY` and so on. There are also builder classes that +can be used to assemble requests with custom headers and request bodies. + +* Classic HttpClient + +Please note that classic request and entity objects are not thread-safe. They must not +be executed multiple times unless their state can be reset. When sharing request objects +and content data between multiple threads access to attributes of those objects must be +synchronized. + +```java +// Get HttpClient singleton +final CloseableHttpClient client = getClient(); +final ClassicHttpRequest httpGet = ClassicRequestBuilder.get() + .setHttpHost(new HttpHost("http", "httpbin.org")) + .setPath("/get") + .build(); +final Message response = client.execute(httpGet, r -> + new Message<>(r, EntityUtils.toString(r.getEntity()))); +System.out.println(response.head().getCode()); +System.out.println(response.body()); +``` + +* Async HttpClient + +Please note that basic request and entity producer objects are not thread-safe. They must +not be executed multiple times unless their state can be reset. When sharing request +objects and content data between multiple threads access to attributers of those objects +must be synchronized. + +```java +// Get HttpClient singleton +final CloseableHttpAsyncClient client = getClient(); +final HttpRequest httpGet = BasicRequestBuilder.get() + .setHttpHost(new HttpHost("http", "httpbin.org")) + .setPath("/get") + .build(); +final Future> future = client.execute( + new BasicRequestProducer(httpGet, null), + new BasicResponseConsumer<>(StringAsyncEntityConsumer::new), + null); +final Message response = future.get(); +System.out.println(response.head().getCode()); +System.out.println(response.body()); +``` + +Please note that the response content is represented as a String for simplicity. In +productive scenarios one should transform the response directly into a high-level value +object, for instance by way of JSON bindings. + +Resource management +------------------ + +There are several ways to ensure HttpClient does not keep any system resources such +persistent connections in the connection pool indefinitely. One can use a dedicated +thread to evict idle or expired connections automatically or manually by explicitly +evicting connections prior or post a long period of inactivity. + +One should also generally limit connection total time to live (TTL) to a finite value. + +```java +final static PoolingHttpClientConnectionManager CONN_MANAGER; + +static { + CONN_MANAGER = PoolingHttpClientConnectionManagerBuilder.create() + .setDefaultConnectionConfig(ConnectionConfig.custom() + .setTimeToLive(TimeValue.ofMinutes(5)) + .build()) + .build(); +} + +static ConnPoolControl getConnPool() { + return CONN_MANAGER; +} +``` +```java +final ConnPoolControl connPool = getConnPool(); +// Close out all connections +connPool.closeIdle(TimeValue.ZERO_MILLISECONDS); +``` + +Connection release +------------------ + +All HttpClient implementations automatically lease connections from the connection +manager and release them back once the message exchange has been fully executed (also +in case of an error or an exception). + +One exception to this principle is when the response object must to be kept open, in +which case the caller is responsible for closing the response object to ensure release +of resources associated with the response stream. Failure to close the response object, +for instance in case of an exception, will likely cause a resource leak and connection +pool resource starvation. + +```java +final CloseableHttpClient client = getClient(); +final HttpHost target = new HttpHost("http", "httpbin.org"); + +final ClassicHttpRequest httpGet = ClassicRequestBuilder.get() + .setHttpHost(target) + .setPath("/get") + .build(); + +final HttpClientContext clientContext = HttpClientContext.create(); +try (final ClassicHttpResponse response = client.executeOpen(target, httpGet, clientContext)) { + System.out.println(response.getCode()); + System.out.println(EntityUtils.toString(response.getEntity())); +} +``` + +Client execution context +------------------ + +HTTP request messages are self-contained and the ability to add custom headers to +the request messages should generally be a sufficient enough customization mechanism for +many use scenarios. However, there are situations when one requires access to a wider +context of request execution or more fine-tuned configuration of the HTTP protocol +execution. The execution context managed by HttpClient is represented by the +`HttpClientContext` class, which basically acts a holder of various attributes that can +be set prior to request execution, updated in the course of the request execution and +the response processing, and interrogated upon the message exchange completion. + +* Classic HttpClient + +```java +final CloseableHttpClient client = getClient(); + +final CookieStore cookieStore = new BasicCookieStore(); + +final HttpClientContext localContext = ContextBuilder.create() + // Bind custom cookie store to the local context + .useCookieStore(cookieStore) + .build(); +// Provide request custom settings +localContext.setRequestConfig(RequestConfig.custom() + .setCookieSpec(CookieSpecs.STANDARD_STRICT) + .build()); + +final ClassicHttpRequest httpGet = ClassicRequestBuilder.get() + .setHttpHost(new HttpHost("http", "httpbin.org")) + .setPath("/cookies") + .build(); +final Message response = client.execute( + httpGet, localContext, r -> + new Message<>(r, EntityUtils.toString(r.getEntity()))); +System.out.println(response.head().getCode()); +System.out.println(response.body()); + +for (Cookie cookie : cookieStore.getCookies()) { + System.out.println("Local cookie: " + cookie); +} +``` + +* Async HttpClient + +```java +final CloseableHttpAsyncClient client = getClient(); + +final CookieStore cookieStore = new BasicCookieStore(); + +final HttpClientContext localContext = ContextBuilder.create() + // Bind custom cookie store to the local context + .useCookieStore(cookieStore) + .build(); +// Provide request custom settings +localContext.setRequestConfig(RequestConfig.custom() + .setCookieSpec(CookieSpecs.STANDARD_STRICT) + .build()); + +final HttpRequest httpGet = BasicRequestBuilder.get() + .setHttpHost(new HttpHost("http", "httpbin.org")) + .setPath("/cookies") + .build(); +final Future> future = client.execute( + new BasicRequestProducer(httpGet, null), + new BasicResponseConsumer<>(StringAsyncEntityConsumer::new), + null, + localContext, + null); +final Message response = future.get(); +System.out.println(response.head().getCode()); +System.out.println(response.body()); + +for (Cookie cookie : cookieStore.getCookies()) { + System.out.println("Local cookie: " + cookie); +} +``` +Please note that while `HttpClientContext` itself is thread-safe, some of its attributes +may not be. It is strongly recommended to have `HttpClientContext` instances associated +with a single message exchange at any given time. It, however, can be benefitial to have +subsequent requests within the same logical HTTP session share the same execution +context. + +```java +final CloseableHttpAsyncClient client = getClient(); + +final CookieStore cookieStore = new BasicCookieStore(); + +// Create session HTTP context +final HttpClientContext localContext = ContextBuilder.create() + // Bind custom cookie store to the local context + .useCookieStore(cookieStore) + .build(); + +for (int i = 1; i <= 3; i++) { + final HttpRequest httpGet = BasicRequestBuilder.get() + .setHttpHost(new HttpHost("http", "httpbin.org")) + .setPath("/cookies") + .build(); + // Share the same HttpClientContext + final Future> future = client.execute( + new BasicRequestProducer(httpGet, null), + new BasicResponseConsumer<>(StringAsyncEntityConsumer::new), + null, + localContext, + null); + final Message response = future.get(); + System.out.println(response.head().getCode()); + System.out.println(response.body()); + + for (Cookie cookie : cookieStore.getCookies()) { + System.out.println("Local cookie: " + cookie); + } +} +``` \ No newline at end of file diff --git a/src/site/markdown/httpcomponents-client-5.7.x/index.md b/src/site/markdown/httpcomponents-client-5.7.x/index.md index 410a3cc..7e0003e 100644 --- a/src/site/markdown/httpcomponents-client-5.7.x/index.md +++ b/src/site/markdown/httpcomponents-client-5.7.x/index.md @@ -20,22 +20,35 @@ HttpClient Overview =================== -The Hyper-Text Transfer Protocol (HTTP) is perhaps the most significant protocol used on the Internet today. Web -services, network-enabled appliances and the growth of network computing continue to expand the role of the HTTP -protocol beyond user-driven web browsers, while increasing the number of applications that require HTTP support. - -Although the java.net package provides basic functionality for accessing resources via HTTP, it doesn't provide the full -flexibility or functionality needed by many applications. HttpClient seeks to fill this void by providing an efficient, -up-to-date, and feature-rich package implementing the client side of the most recent HTTP standards and recommendations. - -Designed for extension while providing robust support for the base HTTP protocol, HttpClient may be of interest to -anyone building HTTP-aware client applications such as web browsers, web service clients, or systems that leverage or -extend the HTTP protocol for distributed communication. +The Hyper-Text Transfer Protocol (HTTP) is perhaps the most significant protocol used on +the Internet today. Web services, network-enabled appliances and the growth of network +computing continue to expand the role of the HTTP protocol beyond user-driven web +browsers, while increasing the number of applications that require HTTP support. + +Although the java.net package provides basic functionality for accessing resources via +HTTP, it doesn't provide the full flexibility or functionality needed by many +applications. HttpClient seeks to fill this void by providing an efficient, up-to-date, +and feature-rich package implementing the client side of the most recent HTTP standards +and recommendations. + +Designed for extension while providing robust support for the base HTTP protocol, +HttpClient may be of interest to anyone building HTTP-aware client applications such as +web browsers, web service clients, or systems that leverage or extend the HTTP protocol +for distributed communication. + +Design objectives and project scope +----------------- +* Full-featured HTTP client with many advanced functions. +* Based on [HttpCore](../httpcomponents-core-5.5.x/index.md). +* Minimal set of mandatory dependencies (HttpCore and SLF4J) +* Other dependencies are optional at runtime or pulled in as transitive dependencies of + optional client modules (cache, observation, reactive, Jakarta REST) Documentation -------------- +=================== 1. Guides + * [Getting started](getting-started.md) * [SSE](server-sent-events.md) - Server side events * [Jakarta REST client](rest-client.md) - Type-safe Jakarta REST client backed by HttpClient * [WebSocket](websocket.md) - Full-duplex messaging over HTTP/1.1 and HTTP/2 @@ -64,32 +77,36 @@ Features - Supports encryption with HTTPS (HTTP over SSL) protocol. - Pluggable TLS strategies. - Transparent message exchanges through HTTP/1.1, HTTP/1.0 and SOCKS proxies. -- Tunneled HTTPS connections through HTTP/1.1 and HTTP/1.0 proxies, via the CONNECT method. +- Tunneled HTTPS connections through HTTP/1.1 and HTTP/1.0 proxies, via the CONNECT + method. - Basic, Digest, Bearer, SCRAM-SHA-256 authentication schemes. - HTTP state management and cookie support. -- Flexible connection management and pooling with STRICT, LAX and OFFLOCK concurrency policies. -- Optional off-lock disposal for blocking connection pools to move slow graceful closes off hot pool locks. -- Basic, Digest, Bearer, and SCRAM-SHA-256 authentication schemes. -- Support for HTTP response caching. Pluggable storage backends based on Ehcache, Memcached, Caffeine. +- Flexible connection management and pooling with STRICT, LAX and OFFLOCK concurrency + policies. +- Optional off-lock disposal for blocking connection pools to move slow graceful closes + off hot pool locks. +- Support for HTTP response caching. Pluggable storage backends based on Ehcache, + Memcached, Caffeine. - Transparent content decompression with deflate, gzip, and optional zstd / brotli codecs. - Support for Unix domain sockets. - Experimental RFC 9218 prioritization (Priority header & PRIORITY_UPDATE for HTTP/2). -- I/O byte counters, connection-pool gauges, and DNS/TLS meters for classic and async clients. +- I/O byte counters, connection-pool gauges, and DNS/TLS meters for classic and async + clients. - Optional SPKI pinning TLS strategy for host / wildcard public-key pinning. -- Async support for 103 Early Hints via a pluggable -- Optional Observability nodule with Micrometer / OpenTelemetry support for request timers/counters, +- Async support for 103 Early Hints via a pluggable strategy +- Optional Observability module with Micrometer / OpenTelemetry support for request + timers/counters. - Optional Server-Sent Events (SSE) module for consuming long-lived event streams over HTTP/1.1 and HTTP/2 using the async transport. - Optional WebSocket module for full-duplex messaging over HTTP/1.1 (Upgrade) and HTTP/2 (Extended CONNECT), with optional permessage-deflate compression. - Source code is freely available under the Apache License. - Standards Compliance -------------------- -HttpClient strives to conform to the following specifications endorsed by the Internet Engineering Task Force (IETF) and -the internet at large: +HttpClient strives to conform to the following specifications endorsed by the Internet +Engineering Task Force (IETF) and the internet at large: - [RFC 9110](https://datatracker.ietf.org/doc/html/rfc9110) - HTTP Semantics - [RFC 9111](https://datatracker.ietf.org/doc/html/rfc9111) - HTTP Caching