Codebase list async-http-client / upstream/2.0.17
New upstream version 2.0.17 Emmanuel Bourg 5 years ago
28 changed file(s) with 251 addition(s) and 124 deletion(s). Raw diff Collapse all Expand all
11 <parent>
22 <groupId>org.asynchttpclient</groupId>
33 <artifactId>async-http-client-project</artifactId>
4 <version>2.0.16</version>
4 <version>2.0.17</version>
55 </parent>
66 <modelVersion>4.0.0</modelVersion>
77 <artifactId>async-http-client</artifactId>
3535 /**
3636 * The Request class can be used to construct HTTP request:
3737 * <blockquote><pre>
38 * Request r = new RequestBuilder().setUrl("url")
39 * .setRealm((new Realm.RealmBuilder()).setPrincipal(user)
40 * .setPassword(admin)
41 * .setRealmName("MyRealm")
42 * .setScheme(Realm.AuthScheme.DIGEST).build());
38 * Request r = new RequestBuilder()
39 * .setUrl("url")
40 * .setRealm(
41 * new Realm.Builder("principal", "password")
42 * .setRealmName("MyRealm")
43 * .setScheme(Realm.AuthScheme.BASIC)
44 * ).build();
4345 * </pre></blockquote>
4446 */
4547 public interface Request {
4648
4749 /**
48 * Return the request's method name (GET, POST, etc.)
49 *
50 * @return the request's method name (GET, POST, etc.)
50 * @return the request's HTTP method (GET, POST, etc.)
5151 */
5252 String getMethod();
5353
54 /**
55 *
56 * @return the uri
57 */
5458 Uri getUri();
5559
60 /**
61 * @return the url (the uri's String form)
62 */
5663 String getUrl();
5764
5865 /**
59 * Return the InetAddress to override
60 *
61 * @return the InetAddress
66 * @return the InetAddress to be used to bypass uri's hostname resolution
6267 */
6368 InetAddress getAddress();
6469
70 /**
71 * @return the local address to bind from
72 */
6573 InetAddress getLocalAddress();
6674
6775 /**
68 * Return the current set of Headers.
69 *
70 * @return a {@link HttpHeaders} contains headers.
76 * @return the HTTP headers
7177 */
7278 HttpHeaders getHeaders();
7379
7480 /**
75 * Return cookies.
76 *
77 * @return an unmodifiable Collection of Cookies
81 * @return the HTTP cookies
7882 */
7983 List<Cookie> getCookies();
8084
8185 /**
82 * Return the current request's body as a byte array
83 *
84 * @return a byte array of the current request's body.
86 * @return the request's body byte array (only non null if it was set this way)
8587 */
8688 byte[] getByteData();
8789
8890 /**
89 * @return the current request's body as a composite of byte arrays
91 * @return the request's body array of byte arrays (only non null if it was set this way)
9092 */
9193 List<byte[]> getCompositeByteData();
9294
9395 /**
94 * Return the current request's body as a string
95 *
96 * @return an String representation of the current request's body.
96 * @return the request's body string (only non null if it was set this way)
9797 */
9898 String getStringData();
9999
100100 /**
101 * Return the current request's body as a ByteBuffer
102 *
103 * @return a ByteBuffer
101 * @return the request's body ByteBuffer (only non null if it was set this way)
104102 */
105103 ByteBuffer getByteBufferData();
106104
107105 /**
108 * Return the current request's body as an InputStream
109 *
110 * @return an InputStream representation of the current request's body.
106 * @return the request's body InputStream (only non null if it was set this way)
111107 */
112108 InputStream getStreamData();
113109
114110 /**
115 * Return the current request's body generator.
116 *
117 * @return A generator for the request body.
111 * @return the request's body BodyGenerator (only non null if it was set this way)
118112 */
119113 BodyGenerator getBodyGenerator();
120114
121115 /**
122 * Return the current form parameters.
123 *
124 * @return the form parameters.
116 * @return the request's form parameters
125117 */
126118 List<Param> getFormParams();
127119
128120 /**
129 * Return the current {@link Part}
130 *
131 * @return the current {@link Part}
121 * @return the multipart parts
132122 */
133123 List<Part> getBodyParts();
134124
135125 /**
136 * Return the virtual host value.
137 *
138 * @return the virtual host value.
126 * @return the virtual host to connect to
139127 */
140128 String getVirtualHost();
141129
142130 /**
143 * Return the query params.
144 *
145 * @return the query parameters
131 * @return the query params resolved from the url/uri
146132 */
147133 List<Param> getQueryParams();
148134
149135 /**
150 * Return the {@link ProxyServer}
151 *
152 * @return the {@link ProxyServer}
136 * @return the proxy server to be used to perform this request (overrides the one defined in config)
153137 */
154138 ProxyServer getProxyServer();
155139
156140 /**
157 * Return the {@link Realm}
158 *
159 * @return the {@link Realm}
141 * @return the realm to be used to perform this request (overrides the one defined in config)
160142 */
161143 Realm getRealm();
162144
163145 /**
164 * Return the {@link File} to upload.
165 *
166 * @return the {@link File} to upload.
146 * @return the file to be uploaded
167147 */
168148 File getFile();
169149
170150 /**
171 * Return follow redirect
172 *
173 * @return {@link Boolean#TRUE} to follow redirect, {@link Boolean#FALSE} if NOT to follow whatever the client config, null otherwise.
151 * @return if this request is to follow redirects. Non null values means "override config value".
174152 */
175153 Boolean getFollowRedirect();
176154
177155 /**
178 * Overrides the config default value
179 * @return the request timeout
156 * @return the request timeout. Non zero values means "override config value".
180157 */
181158 int getRequestTimeout();
182159
183160 /**
184 * Return the HTTP Range header value, or
185 *
186161 * @return the range header value, or 0 is not set.
187162 */
188163 long getRangeOffset();
189164
190165 /**
191 * Return the charset value used when decoding the request's body.
192 *
193166 * @return the charset value used when decoding the request's body.
194167 */
195168 Charset getCharset();
196169
170 /**
171 * @return the strategy to compute ChannelPool's keys
172 */
197173 ChannelPoolPartitioning getChannelPoolPartitioning();
198174
175 /**
176 * @return the NameResolver to be used to resolve hostnams's IP
177 */
199178 NameResolver<InetAddress> getNameResolver();
200179 }
1111 * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
1212 */
1313 package org.asynchttpclient.netty.channel;
14
15 import java.util.concurrent.atomic.AtomicBoolean;
1416
1517 import io.netty.channel.Channel;
1618 import io.netty.channel.ChannelId;
2830
2931 private static final AttributeKey<Object> DEFAULT_ATTRIBUTE = AttributeKey.valueOf("default");
3032 private static final AttributeKey<ChannelId> CHANNEL_ID_ATTRIBUTE = AttributeKey.valueOf("channelId");
33 private static final AttributeKey<AtomicBoolean> INACTIVE_TOKEN_ATTRIBUTE = AttributeKey.valueOf("inactiveToken");
3134
3235 public static Object getAttribute(Channel channel) {
3336 Attribute<Object> attr = channel.attr(DEFAULT_ATTRIBUTE);
4447
4548 public static boolean isChannelValid(Channel channel) {
4649 return channel != null && channel.isActive();
50 }
51
52 public static void setInactiveToken(Channel channel) {
53 channel.attr(INACTIVE_TOKEN_ATTRIBUTE).set(new AtomicBoolean(true));
54 }
55
56 public static boolean getInactiveToken(Channel channel) {
57 return channel != null && channel.attr(INACTIVE_TOKEN_ATTRIBUTE).get().getAndSet(false);
4758 }
4859
4960 public static ChannelId getChannelId(Channel channel) {
9494
9595 public void onSuccess(Channel channel, InetSocketAddress remoteAddress) {
9696
97 Channels.setInactiveToken(channel);
98
9799 TimeoutsHolder timeoutsHolder = future.getTimeoutsHolder();
98100
99101 if (futureIsAlreadyCancelled(channel)) {
197197
198198 @Override
199199 public void handleException(NettyResponseFuture<?> future, Throwable e) {
200 logger.warn("onError {}", e);
200 logger.warn("onError", e);
201201
202202 try {
203203 WebSocketUpgradeHandler h = (WebSocketUpgradeHandler) future.getAsyncHandler();
6767 Realm proxyRealm = future.getProxyRealm();
6868
6969 if (proxyRealm == null) {
70 LOGGER.info("Can't handle 407 as there's no proxyRealm");
70 LOGGER.debug("Can't handle 407 as there's no proxyRealm");
7171 return false;
7272 }
7373
6363 HttpRequest httpRequest) {
6464
6565 if (realm == null) {
66 LOGGER.info("Can't handle 401 as there's no realm");
66 LOGGER.debug("Can't handle 401 as there's no realm");
6767 return false;
6868 }
6969
1818 import java.net.InetAddress;
1919 import java.net.InetSocketAddress;
2020 import java.util.List;
21 import java.util.concurrent.RejectedExecutionException;
2122
2223 import org.asynchttpclient.AsyncHandler;
2324 import org.asynchttpclient.AsyncHttpClientConfig;
6566
6667 try {
6768 connect0(bootstrap, connectListener, remoteAddress);
68 } catch (Throwable e) {
69 // workaround for https://github.com/netty/netty/issues/5387
69 } catch (RejectedExecutionException e) {
7070 if (clientState.isClosed()) {
7171 connectListener.onFailure(null, e);
7272 } else {
1919 import static org.asynchttpclient.util.MiscUtils.*;
2020 import static org.asynchttpclient.ws.WebSocketUtils.getKey;
2121 import io.netty.buffer.ByteBuf;
22 import io.netty.buffer.Unpooled;
2223 import io.netty.handler.codec.http.DefaultFullHttpRequest;
2324 import io.netty.handler.codec.http.DefaultHttpRequest;
2425 import io.netty.handler.codec.http.HttpHeaders;
146147 nettyRequest = new NettyRequest(httpRequest, null);
147148
148149 } else if (body == null) {
149 httpRequest = new DefaultFullHttpRequest(httpVersion, method, requestUri);
150 httpRequest = new DefaultFullHttpRequest(httpVersion, method, requestUri, Unpooled.EMPTY_BUFFER);
150151 nettyRequest = new NettyRequest(httpRequest, null);
151152
152153 } else {
404404 }
405405
406406 public void handleUnexpectedClosedChannel(Channel channel, NettyResponseFuture<?> future) {
407 if (future.isDone()) {
408 channelManager.closeChannel(channel);
409 } else if (future.incrementRetryAndCheck() && retry(future)) {
410 future.pendingException = null;
411 } else {
412 abort(channel, future, future.pendingException != null ? future.pendingException : RemotelyClosedException.INSTANCE);
407 if (Channels.getInactiveToken(channel)) {
408 if (future.isDone()) {
409 channelManager.closeChannel(channel);
410 } else if (future.incrementRetryAndCheck() && retry(future)) {
411 future.pendingException = null;
412 } else {
413 abort(channel, future, future.pendingException != null ? future.pendingException : RemotelyClosedException.INSTANCE);
414 }
413415 }
414416 }
415417
1616 import io.netty.handler.ssl.SslContext;
1717 import io.netty.handler.ssl.SslContextBuilder;
1818 import io.netty.handler.ssl.SslProvider;
19 import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
2019
2120 import javax.net.ssl.SSLEngine;
2221 import javax.net.ssl.SSLException;
0 /*
1 * Copyright 2014 The Netty Project
2 *
3 * The Netty Project licenses this file to you under the Apache License,
4 * version 2.0 (the "License"); you may not use this file except in compliance
5 * with the License. You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 * License for the specific language governing permissions and limitations
13 * under the License.
14 */
15 package org.asynchttpclient.netty.ssl;
16
17 import io.netty.handler.ssl.util.SimpleTrustManagerFactory;
18 import io.netty.util.internal.EmptyArrays;
19
20 import java.net.Socket;
21 import java.security.KeyStore;
22 import java.security.cert.X509Certificate;
23
24 import javax.net.ssl.ManagerFactoryParameters;
25 import javax.net.ssl.SSLEngine;
26 import javax.net.ssl.TrustManager;
27 import javax.net.ssl.TrustManagerFactory;
28 import javax.net.ssl.X509ExtendedTrustManager;
29
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 //TODO: Replace this with Netty's InsecureTrustManager once it creates X509ExtendedTrustManager.
34 //
35 // When a server mandates the authentication of a client certificate, JDK internally wraps a TrustManager
36 // with AbstractTrustManagerWrapper unless it extends X509ExtendedTrustManager. AbstractTrustManagerWrapper
37 // performs an additional check (DN comparison), making InsecureTrustManager not insecure enough.
38 //
39 // To work around this problem, we forked Netty's InsecureTrustManagerFactory and made its TrustManager
40 // implementation extend X509ExtendedTrustManager instead of X509TrustManager.
41 // see https://github.com/netty/netty/issues/5910
42 public final class InsecureTrustManagerFactory extends SimpleTrustManagerFactory {
43
44 private static final Logger logger = LoggerFactory.getLogger(InsecureTrustManagerFactory.class);
45
46 public static final TrustManagerFactory INSTANCE = new InsecureTrustManagerFactory();
47
48 private static final TrustManager tm = new X509ExtendedTrustManager() {
49 @Override
50 public void checkClientTrusted(X509Certificate[] chain, String s) {
51 log("client", chain);
52 }
53
54 @Override
55 public void checkClientTrusted(X509Certificate[] chain, String s, Socket socket) {
56 log("client", chain);
57 }
58
59 @Override
60 public void checkClientTrusted(X509Certificate[] chain, String s, SSLEngine sslEngine) {
61 log("client", chain);
62 }
63
64 @Override
65 public void checkServerTrusted(X509Certificate[] chain, String s) {
66 log("server", chain);
67 }
68
69 @Override
70 public void checkServerTrusted(X509Certificate[] chain, String s, Socket socket) {
71 log("server", chain);
72 }
73
74 @Override
75 public void checkServerTrusted(X509Certificate[] chain, String s, SSLEngine sslEngine) {
76 log("server", chain);
77 }
78
79 @Override
80 public X509Certificate[] getAcceptedIssuers() {
81 return EmptyArrays.EMPTY_X509_CERTIFICATES;
82 }
83
84 private void log(String type, X509Certificate[] chain) {
85 logger.debug("Accepting a {} certificate: {}", type, chain[0].getSubjectDN());
86 }
87 };
88
89 private InsecureTrustManagerFactory() {
90 }
91
92 @Override
93 protected void engineInit(KeyStore keyStore) throws Exception {
94 }
95
96 @Override
97 protected void engineInit(ManagerFactoryParameters managerFactoryParameters) throws Exception {
98 }
99
100 @Override
101 protected TrustManager[] engineGetTrustManagers() {
102 return new TrustManager[] { tm };
103 }
104 }
2424
2525 protected void configureSslEngine(SSLEngine sslEngine, AsyncHttpClientConfig config) {
2626 sslEngine.setUseClientMode(true);
27 if (!config.isAcceptAnyCertificate()) {
28 SSLParameters params = sslEngine.getSSLParameters();
29 params.setEndpointIdentificationAlgorithm("HTTPS");
30 sslEngine.setSSLParameters(params);
31 }
27 SSLParameters params = sslEngine.getSSLParameters();
28 params.setEndpointIdentificationAlgorithm("HTTPS");
29 sslEngine.setSSLParameters(params);
3230
3331 if (isNonEmpty(config.getEnabledProtocols()))
3432 sslEngine.setEnabledProtocols(config.getEnabledProtocols());
1111 org.asynchttpclient.compressionEnforced=false
1212 org.asynchttpclient.userAgent=AHC/2.0
1313 org.asynchttpclient.enabledProtocols=TLSv1.2, TLSv1.1, TLSv1
14 org.asynchttpclient.enabledCipherSuites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
14 org.asynchttpclient.enabledCipherSuites=TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA
1515 org.asynchttpclient.useProxySelector=false
1616 org.asynchttpclient.useProxyProperties=false
1717 org.asynchttpclient.validateResponseHeaders=true
3333
3434 public class MultipartBodyTest {
3535
36 @Test
37 public void transferWithCopy() throws Exception {
38 try (MultipartBody multipartBody = buildMultipart()) {
39 long tranferred = transferWithCopy(multipartBody);
40 assertEquals(tranferred, multipartBody.getContentLength());
36 private static final List<Part> PARTS = new ArrayList<>();
37
38 static {
39 try {
40 PARTS.add(new FilePart("filePart", getTestfile()));
41 } catch (URISyntaxException e) {
42 throw new ExceptionInInitializerError(e);
4143 }
44 PARTS.add(new ByteArrayPart("baPart", "testMultiPart".getBytes(UTF_8), "application/test", UTF_8, "fileName"));
45 PARTS.add(new StringPart("stringPart", "testString"));
4246 }
4347
44 @Test
45 public void transferZeroCopy() throws Exception {
46 try (MultipartBody multipartBody = buildMultipart()) {
47 long tranferred = transferZeroCopy(multipartBody);
48 assertEquals(tranferred, multipartBody.getContentLength());
49 }
50 }
51
52 private File getTestfile() throws URISyntaxException {
48 private static File getTestfile() throws URISyntaxException {
5349 final ClassLoader cl = MultipartBodyTest.class.getClassLoader();
5450 final URL url = cl.getResource("textfile.txt");
5551 assertNotNull(url);
5652 return new File(url.toURI());
5753 }
5854
59 private MultipartBody buildMultipart() throws URISyntaxException {
60 List<Part> parts = new ArrayList<>();
61 parts.add(new FilePart("filePart", getTestfile()));
62 parts.add(new ByteArrayPart("baPart", "testMultiPart".getBytes(UTF_8), "application/test", UTF_8, "fileName"));
63 parts.add(new StringPart("stringPart", "testString"));
64 return MultipartUtils.newMultipartBody(parts, HttpHeaders.EMPTY_HEADERS);
55 private static long MAX_MULTIPART_CONTENT_LENGTH_ESTIMATE;
56
57 static {
58 try (MultipartBody dummyBody = buildMultipart()) {
59 // separator is random
60 MAX_MULTIPART_CONTENT_LENGTH_ESTIMATE = dummyBody.getContentLength() + 100;
61 } catch (IOException e) {
62 throw new ExceptionInInitializerError(e);
63 }
6564 }
6665
67 private long transferWithCopy(MultipartBody multipartBody) throws IOException {
68 final ByteBuf buffer = Unpooled.buffer(8192);
69 while (multipartBody.transferTo(buffer) != BodyState.STOP) {
70 }
71 return buffer.readableBytes();
66 private static MultipartBody buildMultipart() {
67 return MultipartUtils.newMultipartBody(PARTS, HttpHeaders.EMPTY_HEADERS);
7268 }
7369
74 private static long transferZeroCopy(MultipartBody multipartBody) throws IOException {
70 @Test
71 public void transferWithCopy() throws Exception {
72 for (int bufferLength = 1; bufferLength < MAX_MULTIPART_CONTENT_LENGTH_ESTIMATE + 1; bufferLength++) {
73 try (MultipartBody multipartBody = buildMultipart()) {
74 long tranferred = transferWithCopy(multipartBody, bufferLength);
75 assertEquals(tranferred, multipartBody.getContentLength());
76 }
77 }
78 }
7579
76 final ByteBuffer buffer = ByteBuffer.allocate(8192);
80 @Test
81 public void transferZeroCopy() throws Exception {
82 for (int bufferLength = 1; bufferLength < MAX_MULTIPART_CONTENT_LENGTH_ESTIMATE + 1; bufferLength++) {
83 try (MultipartBody multipartBody = buildMultipart()) {
84 long tranferred = transferZeroCopy(multipartBody, bufferLength);
85 assertEquals(tranferred, multipartBody.getContentLength());
86 }
87 }
88 }
89
90 private static long transferWithCopy(MultipartBody multipartBody, int bufferSize) throws IOException {
91 long transferred = 0;
92 final ByteBuf buffer = Unpooled.buffer(bufferSize);
93 try {
94 while (multipartBody.transferTo(buffer) != BodyState.STOP) {
95 transferred += buffer.readableBytes();
96 buffer.clear();
97 }
98 return transferred;
99 } finally {
100 buffer.release();
101 }
102 }
103
104 private static long transferZeroCopy(MultipartBody multipartBody, int bufferSize) throws IOException {
105
106 final ByteBuffer buffer = ByteBuffer.allocate(bufferSize);
77107 final AtomicLong transferred = new AtomicLong();
78108
79109 WritableByteChannel mockChannel = new WritableByteChannel() {
11 <parent>
22 <groupId>org.asynchttpclient</groupId>
33 <artifactId>async-http-client-project</artifactId>
4 <version>2.0.16</version>
4 <version>2.0.17</version>
55 </parent>
66 <modelVersion>4.0.0</modelVersion>
77 <artifactId>async-http-client-example</artifactId>
11 <parent>
22 <groupId>org.asynchttpclient</groupId>
33 <artifactId>async-http-client-extras-parent</artifactId>
4 <version>2.0.16</version>
4 <version>2.0.17</version>
55 </parent>
66 <modelVersion>4.0.0</modelVersion>
77 <artifactId>async-http-client-extras-guava</artifactId>
1717 <parent>
1818 <artifactId>async-http-client-extras-parent</artifactId>
1919 <groupId>org.asynchttpclient</groupId>
20 <version>2.0.16</version>
20 <version>2.0.17</version>
2121 </parent>
2222 <artifactId>async-http-client-extras-jdeferred</artifactId>
2323 <name>Asynchronous Http Client JDeferred Extras</name>
11 <parent>
22 <groupId>org.asynchttpclient</groupId>
33 <artifactId>async-http-client-project</artifactId>
4 <version>2.0.16</version>
4 <version>2.0.17</version>
55 </parent>
66 <modelVersion>4.0.0</modelVersion>
77 <artifactId>async-http-client-extras-parent</artifactId>
11 <parent>
22 <groupId>org.asynchttpclient</groupId>
33 <artifactId>async-http-client-extras-parent</artifactId>
4 <version>2.0.16</version>
4 <version>2.0.17</version>
55 </parent>
66 <modelVersion>4.0.0</modelVersion>
77 <artifactId>async-http-client-extras-registry</artifactId>
22 <parent>
33 <artifactId>async-http-client-extras-parent</artifactId>
44 <groupId>org.asynchttpclient</groupId>
5 <version>2.0.16</version>
5 <version>2.0.17</version>
66 </parent>
77 <artifactId>async-http-client-extras-rxjava</artifactId>
88 <name>Asynchronous Http Client RxJava Extras</name>
22 <parent>
33 <artifactId>async-http-client-extras-parent</artifactId>
44 <groupId>org.asynchttpclient</groupId>
5 <version>2.0.16</version>
5 <version>2.0.17</version>
66 </parent>
77 <artifactId>async-http-client-extras-simple</artifactId>
88 <name>Asynchronous Http Simple Client</name>
1919 <parent>
2020 <groupId>org.asynchttpclient</groupId>
2121 <artifactId>netty-bp</artifactId>
22 <version>2.0.16</version>
22 <version>2.0.17</version>
2323 </parent>
2424
2525 <artifactId>netty-codec-dns</artifactId>
11 <parent>
22 <groupId>org.asynchttpclient</groupId>
33 <artifactId>async-http-client-project</artifactId>
4 <version>2.0.16</version>
4 <version>2.0.17</version>
55 </parent>
66 <modelVersion>4.0.0</modelVersion>
77 <artifactId>netty-bp</artifactId>
1919 <parent>
2020 <groupId>org.asynchttpclient</groupId>
2121 <artifactId>netty-bp</artifactId>
22 <version>2.0.16</version>
22 <version>2.0.17</version>
2323 </parent>
2424
2525 <artifactId>netty-resolver</artifactId>
88 <parent>
99 <groupId>org.asynchttpclient</groupId>
1010 <artifactId>netty-bp</artifactId>
11 <version>2.0.16</version>
11 <version>2.0.17</version>
1212 </parent>
1313
1414 <artifactId>netty-resolver-dns</artifactId>
11 <parent>
22 <groupId>org.asynchttpclient</groupId>
33 <artifactId>async-http-client-project</artifactId>
4 <version>2.0.16</version>
4 <version>2.0.17</version>
55 </parent>
66 <modelVersion>4.0.0</modelVersion>
77 <artifactId>async-http-client-netty-utils</artifactId>
88 <groupId>org.asynchttpclient</groupId>
99 <artifactId>async-http-client-project</artifactId>
1010 <name>Asynchronous Http Client Project</name>
11 <version>2.0.16</version>
11 <version>2.0.17</version>
1212 <packaging>pom</packaging>
1313 <description>
1414 The Async Http Client (AHC) library's purpose is to allow Java
373373 <surefire.redirectTestOutputToFile>true</surefire.redirectTestOutputToFile>
374374 <source.property>1.8</source.property>
375375 <target.property>1.8</target.property>
376 <netty.version>4.0.41.Final</netty.version>
376 <netty.version>4.0.42.Final</netty.version>
377377 <slf4j.version>1.7.21</slf4j.version>
378378 <logback.version>1.1.7</logback.version>
379379 <testng.version>6.9.10</testng.version>