View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.hc.client5.http.examples;
29  
30  import java.net.InetAddress;
31  import java.net.UnknownHostException;
32  import java.nio.charset.CodingErrorAction;
33  import java.nio.charset.StandardCharsets;
34  import java.util.Arrays;
35  import java.util.Collections;
36  
37  import javax.net.ssl.SSLContext;
38  
39  import org.apache.hc.client5.http.DnsResolver;
40  import org.apache.hc.client5.http.HttpRoute;
41  import org.apache.hc.client5.http.SystemDefaultDnsResolver;
42  import org.apache.hc.client5.http.auth.StandardAuthScheme;
43  import org.apache.hc.client5.http.auth.CredentialsProvider;
44  import org.apache.hc.client5.http.classic.methods.HttpGet;
45  import org.apache.hc.client5.http.config.RequestConfig;
46  import org.apache.hc.client5.http.cookie.BasicCookieStore;
47  import org.apache.hc.client5.http.cookie.StandardCookieSpec;
48  import org.apache.hc.client5.http.cookie.CookieStore;
49  import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
50  import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
51  import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
52  import org.apache.hc.client5.http.impl.classic.HttpClients;
53  import org.apache.hc.client5.http.impl.io.ManagedHttpClientConnectionFactory;
54  import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
55  import org.apache.hc.client5.http.io.ManagedHttpClientConnection;
56  import org.apache.hc.client5.http.protocol.HttpClientContext;
57  import org.apache.hc.client5.http.socket.ConnectionSocketFactory;
58  import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory;
59  import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
60  import org.apache.hc.core5.http.ClassicHttpRequest;
61  import org.apache.hc.core5.http.ClassicHttpResponse;
62  import org.apache.hc.core5.http.Header;
63  import org.apache.hc.core5.http.HttpHost;
64  import org.apache.hc.core5.http.ParseException;
65  import org.apache.hc.core5.http.config.CharCodingConfig;
66  import org.apache.hc.core5.http.config.Http1Config;
67  import org.apache.hc.core5.http.config.Registry;
68  import org.apache.hc.core5.http.config.RegistryBuilder;
69  import org.apache.hc.core5.http.impl.io.DefaultClassicHttpResponseFactory;
70  import org.apache.hc.core5.http.impl.io.DefaultHttpRequestWriterFactory;
71  import org.apache.hc.core5.http.impl.io.DefaultHttpResponseParser;
72  import org.apache.hc.core5.http.impl.io.DefaultHttpResponseParserFactory;
73  import org.apache.hc.core5.http.io.HttpConnectionFactory;
74  import org.apache.hc.core5.http.io.HttpMessageParser;
75  import org.apache.hc.core5.http.io.HttpMessageParserFactory;
76  import org.apache.hc.core5.http.io.HttpMessageWriterFactory;
77  import org.apache.hc.core5.http.io.SocketConfig;
78  import org.apache.hc.core5.http.io.entity.EntityUtils;
79  import org.apache.hc.core5.http.message.BasicHeader;
80  import org.apache.hc.core5.http.message.BasicLineParser;
81  import org.apache.hc.core5.http.message.LineParser;
82  import org.apache.hc.core5.pool.PoolConcurrencyPolicy;
83  import org.apache.hc.core5.pool.PoolReusePolicy;
84  import org.apache.hc.core5.ssl.SSLContexts;
85  import org.apache.hc.core5.util.CharArrayBuffer;
86  import org.apache.hc.core5.util.TimeValue;
87  import org.apache.hc.core5.util.Timeout;
88  
89  /**
90   * This example demonstrates how to customize and configure the most common aspects
91   * of HTTP request execution and connection management.
92   */
93  public class ClientConfiguration {
94  
95      public final static void main(final String[] args) throws Exception {
96  
97          // Use custom message parser / writer to customize the way HTTP
98          // messages are parsed from and written out to the data stream.
99          final HttpMessageParserFactory<ClassicHttpResponse> responseParserFactory = new DefaultHttpResponseParserFactory() {
100 
101             @Override
102             public HttpMessageParser<ClassicHttpResponse> create(final Http1Config h1Config) {
103                 final LineParser lineParser = new BasicLineParser() {
104 
105                     @Override
106                     public Header parseHeader(final CharArrayBuffer buffer) {
107                         try {
108                             return super.parseHeader(buffer);
109                         } catch (final ParseException ex) {
110                             return new BasicHeader(buffer.toString(), null);
111                         }
112                     }
113 
114                 };
115                 return new DefaultHttpResponseParser(lineParser, DefaultClassicHttpResponseFactory.INSTANCE, h1Config);
116             }
117 
118         };
119         final HttpMessageWriterFactory<ClassicHttpRequest> requestWriterFactory = new DefaultHttpRequestWriterFactory();
120 
121         // Create HTTP/1.1 protocol configuration
122         final Http1Config h1Config = Http1Config.custom()
123                 .setMaxHeaderCount(200)
124                 .setMaxLineLength(2000)
125                 .build();
126         // Create connection configuration
127         final CharCodingConfig connectionConfig = CharCodingConfig.custom()
128                 .setMalformedInputAction(CodingErrorAction.IGNORE)
129                 .setUnmappableInputAction(CodingErrorAction.IGNORE)
130                 .setCharset(StandardCharsets.UTF_8)
131                 .build();
132 
133         // Use a custom connection factory to customize the process of
134         // initialization of outgoing HTTP connections. Beside standard connection
135         // configuration parameters HTTP connection factory can define message
136         // parser / writer routines to be employed by individual connections.
137         final HttpConnectionFactory<ManagedHttpClientConnection> connFactory = new ManagedHttpClientConnectionFactory(
138                 h1Config, connectionConfig, requestWriterFactory, responseParserFactory);
139 
140         // Client HTTP connection objects when fully initialized can be bound to
141         // an arbitrary network socket. The process of network socket initialization,
142         // its connection to a remote address and binding to a local one is controlled
143         // by a connection socket factory.
144 
145         // SSL context for secure connections can be created either based on
146         // system or application specific properties.
147         final SSLContext sslcontext = SSLContexts.createSystemDefault();
148 
149         // Create a registry of custom connection socket factories for supported
150         // protocol schemes.
151         final Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
152             .register("http", PlainConnectionSocketFactory.INSTANCE)
153             .register("https", new SSLConnectionSocketFactory(sslcontext))
154             .build();
155 
156         // Use custom DNS resolver to override the system DNS resolution.
157         final DnsResolver dnsResolver = new SystemDefaultDnsResolver() {
158 
159             @Override
160             public InetAddress[] resolve(final String host) throws UnknownHostException {
161                 if (host.equalsIgnoreCase("myhost")) {
162                     return new InetAddress[] { InetAddress.getByAddress(new byte[] {127, 0, 0, 1}) };
163                 } else {
164                     return super.resolve(host);
165                 }
166             }
167 
168         };
169 
170         // Create a connection manager with custom configuration.
171         final PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(
172                 socketFactoryRegistry, PoolConcurrencyPolicy.STRICT, PoolReusePolicy.LIFO, TimeValue.ofMinutes(5),
173                 null, dnsResolver, null);
174 
175         // Create socket configuration
176         final SocketConfig socketConfig = SocketConfig.custom()
177             .setTcpNoDelay(true)
178             .build();
179         // Configure the connection manager to use socket configuration either
180         // by default or for a specific host.
181         connManager.setDefaultSocketConfig(socketConfig);
182         // Validate connections after 1 sec of inactivity
183         connManager.setValidateAfterInactivity(TimeValue.ofSeconds(10));
184 
185         // Configure total max or per route limits for persistent connections
186         // that can be kept in the pool or leased by the connection manager.
187         connManager.setMaxTotal(100);
188         connManager.setDefaultMaxPerRoute(10);
189         connManager.setMaxPerRoute(new HttpRoute(new HttpHost("somehost", 80)), 20);
190 
191         // Use custom cookie store if necessary.
192         final CookieStore cookieStore = new BasicCookieStore();
193         // Use custom credentials provider if necessary.
194         final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
195         // Create global request configuration
196         final RequestConfig defaultRequestConfig = RequestConfig.custom()
197             .setCookieSpec(StandardCookieSpec.STRICT)
198             .setExpectContinueEnabled(true)
199             .setTargetPreferredAuthSchemes(Arrays.asList(StandardAuthScheme.NTLM, StandardAuthScheme.DIGEST))
200             .setProxyPreferredAuthSchemes(Collections.singletonList(StandardAuthScheme.BASIC))
201             .build();
202 
203         // Create an HttpClient with the given custom dependencies and configuration.
204 
205         try (final CloseableHttpClient httpclient = HttpClients.custom()
206                 .setConnectionManager(connManager)
207                 .setDefaultCookieStore(cookieStore)
208                 .setDefaultCredentialsProvider(credentialsProvider)
209                 .setProxy(new HttpHost("myproxy", 8080))
210                 .setDefaultRequestConfig(defaultRequestConfig)
211                 .build()) {
212             final HttpGet httpget = new HttpGet("http://httpbin.org/get");
213             // Request configuration can be overridden at the request level.
214             // They will take precedence over the one set at the client level.
215             final RequestConfig requestConfig = RequestConfig.copy(defaultRequestConfig)
216                     .setConnectionRequestTimeout(Timeout.ofSeconds(5))
217                     .setConnectTimeout(Timeout.ofSeconds(5))
218                     .setProxy(new HttpHost("myotherproxy", 8080))
219                     .build();
220             httpget.setConfig(requestConfig);
221 
222             // Execution context can be customized locally.
223             final HttpClientContext context = HttpClientContext.create();
224             // Contextual attributes set the local context level will take
225             // precedence over those set at the client level.
226             context.setCookieStore(cookieStore);
227             context.setCredentialsProvider(credentialsProvider);
228 
229             System.out.println("Executing request " + httpget.getMethod() + " " + httpget.getUri());
230             try (final CloseableHttpResponse response = httpclient.execute(httpget, context)) {
231                 System.out.println("----------------------------------------");
232                 System.out.println(response.getCode() + " " + response.getReasonPhrase());
233                 System.out.println(EntityUtils.toString(response.getEntity()));
234 
235                 // Once the request has been executed the local context can
236                 // be used to examine updated state and various objects affected
237                 // by the request execution.
238 
239                 // Last executed request
240                 context.getRequest();
241                 // Execution route
242                 context.getHttpRoute();
243                 // Auth exchanges
244                 context.getAuthExchanges();
245                 // Cookie origin
246                 context.getCookieOrigin();
247                 // Cookie spec used
248                 context.getCookieSpec();
249                 // User security token
250                 context.getUserToken();
251 
252             }
253         }
254     }
255 
256 }
257