Codebase list async-http-client / 50a5dd4
New upstream version 2.12.3 Emmanuel Bourg 2 years ago
24 changed file(s) with 312 addition(s) and 32 deletion(s). Raw diff Collapse all Expand all
44 <parent>
55 <groupId>org.asynchttpclient</groupId>
66 <artifactId>async-http-client-project</artifactId>
7 <version>2.12.2</version>
7 <version>2.12.3</version>
88 </parent>
99
1010 <artifactId>async-http-client-bom</artifactId>
11 <parent>
22 <groupId>org.asynchttpclient</groupId>
33 <artifactId>async-http-client-project</artifactId>
4 <version>2.12.2</version>
4 <version>2.12.3</version>
55 </parent>
66 <modelVersion>4.0.0</modelVersion>
77 <artifactId>async-http-client</artifactId>
3737
3838 import static io.netty.handler.codec.http.HttpHeaderNames.*;
3939 import static org.asynchttpclient.util.HttpConstants.Methods.GET;
40 import static org.asynchttpclient.util.HttpConstants.Methods.HEAD;
41 import static org.asynchttpclient.util.HttpConstants.Methods.OPTIONS;
4042 import static org.asynchttpclient.util.HttpConstants.ResponseStatusCodes.*;
4143 import static org.asynchttpclient.util.HttpUtils.followRedirect;
4244 import static org.asynchttpclient.util.MiscUtils.isNonEmpty;
8688
8789 String originalMethod = request.getMethod();
8890 boolean switchToGet = !originalMethod.equals(GET)
89 && (statusCode == MOVED_PERMANENTLY_301 || statusCode == SEE_OTHER_303 || (statusCode == FOUND_302 && !config.isStrict302Handling()));
91 && !originalMethod.equals(OPTIONS) && !originalMethod.equals(HEAD) && (statusCode == MOVED_PERMANENTLY_301 || statusCode == SEE_OTHER_303 || (statusCode == FOUND_302 && !config.isStrict302Handling()));
9092 boolean keepBody = statusCode == TEMPORARY_REDIRECT_307 || statusCode == PERMANENT_REDIRECT_308 || (statusCode == FOUND_302 && config.isStrict302Handling());
9193
9294 final RequestBuilder requestBuilder = new RequestBuilder(switchToGet ? GET : originalMethod)
125127 HttpHeaders responseHeaders = response.headers();
126128 String location = responseHeaders.get(LOCATION);
127129 Uri newUri = Uri.create(future.getUri(), location);
128
129130 LOGGER.debug("Redirecting to {}", newUri);
130131
131132 CookieStore cookieStore = config.getCookieStore();
139139 if (connect) {
140140 // assign proxy-auth as configured on request
141141 headers.set(PROXY_AUTHORIZATION, request.getHeaders().getAll(PROXY_AUTHORIZATION));
142 headers.set(USER_AGENT, request.getHeaders().getAll(USER_AGENT));
142143
143144 } else {
144145 // assign headers as configured on request
274274
275275 // some headers are only set when performing the first request
276276 HttpHeaders headers = future.getNettyRequest().getHttpRequest().headers();
277 if(proxy != null && proxy.getCustomHeaders() != null ) {
278 HttpHeaders customHeaders = proxy.getCustomHeaders().apply(request);
279 if(customHeaders != null) {
280 headers.add(customHeaders);
281 }
282 }
277283 Realm realm = future.getRealm();
278284 Realm proxyRealm = future.getProxyRealm();
279285 requestFactory.addAuthorizationHeader(headers, perConnectionAuthorizationHeader(request, proxy, realm));
463469 public void abort(Channel channel, NettyResponseFuture<?> future, Throwable t) {
464470
465471 if (channel != null) {
466 Object attribute = Channels.getAttribute(future.channel());
472 Object attribute = Channels.getAttribute(channel);
467473 if (attribute instanceof StreamedResponsePublisher) {
468474 ((StreamedResponsePublisher) attribute).setError(t);
469475 }
1515 */
1616 package org.asynchttpclient.proxy;
1717
18 import io.netty.handler.codec.http.HttpHeaders;
19
1820 import org.asynchttpclient.Realm;
21 import org.asynchttpclient.Request;
1922
2023 import java.util.ArrayList;
2124 import java.util.Collections;
2225 import java.util.List;
26 import java.util.function.Function;
2327
2428 import static org.asynchttpclient.util.Assertions.assertNotNull;
2529 import static org.asynchttpclient.util.MiscUtils.isNonEmpty;
3539 private final Realm realm;
3640 private final List<String> nonProxyHosts;
3741 private final ProxyType proxyType;
42 private final Function<Request, HttpHeaders> customHeaders;
3843
3944 public ProxyServer(String host, int port, int securedPort, Realm realm, List<String> nonProxyHosts,
40 ProxyType proxyType) {
45 ProxyType proxyType, Function<Request, HttpHeaders> customHeaders) {
4146 this.host = host;
4247 this.port = port;
4348 this.securedPort = securedPort;
4449 this.realm = realm;
4550 this.nonProxyHosts = nonProxyHosts;
4651 this.proxyType = proxyType;
52 this.customHeaders = customHeaders;
53 }
54
55 public ProxyServer(String host, int port, int securedPort, Realm realm, List<String> nonProxyHosts,
56 ProxyType proxyType) {
57 this(host, port, securedPort, realm, nonProxyHosts, proxyType, null);
4758 }
4859
4960 public String getHost() {
6879
6980 public ProxyType getProxyType() {
7081 return proxyType;
82 }
83
84 public Function<Request, HttpHeaders> getCustomHeaders() {
85 return customHeaders;
7186 }
7287
7388 /**
117132 private Realm realm;
118133 private List<String> nonProxyHosts;
119134 private ProxyType proxyType;
135 private Function<Request, HttpHeaders> customHeaders;
120136
121137 public Builder(String host, int port) {
122138 this.host = host;
156172 return this;
157173 }
158174
175 public Builder setCustomHeaders(Function<Request, HttpHeaders> customHeaders) {
176 this.customHeaders = customHeaders;
177 return this;
178 }
179
159180 public ProxyServer build() {
160181 List<String> nonProxyHosts = this.nonProxyHosts != null ? Collections.unmodifiableList(this.nonProxyHosts)
161182 : Collections.emptyList();
162183 ProxyType proxyType = this.proxyType != null ? this.proxyType : ProxyType.HTTP;
163 return new ProxyServer(host, port, securedPort, realm, nonProxyHosts, proxyType);
184 return new ProxyServer(host, port, securedPort, realm, nonProxyHosts, proxyType, customHeaders);
164185 }
165186 }
166187 }
427427 }));
428428 }
429429
430 // This test is flaky - see https://github.com/AsyncHttpClient/async-http-client/issues/1728#issuecomment-699962325
431 // For now, just run again if fails
430432 @Test(groups = "online")
431433 public void asyncOptionsTest() throws Throwable {
432434
3030 import java.util.concurrent.ExecutionException;
3131 import java.util.concurrent.Future;
3232
33 import static io.netty.handler.codec.http.HttpHeaderNames.PROXY_AUTHENTICATE;
34 import static io.netty.handler.codec.http.HttpHeaderNames.PROXY_AUTHORIZATION;
33 import static io.netty.handler.codec.http.HttpHeaderNames.*;
3534 import static org.asynchttpclient.Dsl.*;
3635 import static org.asynchttpclient.test.TestUtils.addHttpConnector;
3736 import static org.asynchttpclient.test.TestUtils.addHttpsConnector;
37 import static org.asynchttpclient.config.AsyncHttpClientConfigDefaults.*;
3838
3939 /**
40 * Test that validates that when having an HTTP proxy and trying to access an HTTPS through the proxy the proxy credentials should be passed during the CONNECT request.
40 * Test that validates that when having an HTTP proxy and trying to access an HTTPS
41 * through the proxy the proxy credentials and a custom user-agent (if set) should be passed during the CONNECT request.
4142 */
4243 public class BasicHttpProxyToHttpsTest {
4344
4445 private static final Logger LOGGER = LoggerFactory.getLogger(BasicHttpProxyToHttpsTest.class);
46 private static final String CUSTOM_USER_AGENT = "custom-user-agent";
4547
4648 private int httpPort;
4749 private int proxyPort;
6567 ConnectHandler connectHandler = new ConnectHandler() {
6668
6769 @Override
70 // This proxy receives a CONNECT request from the client before making the real request for the target host.
6871 protected boolean handleAuthentication(HttpServletRequest request, HttpServletResponse response, String address) {
72
73 // If the userAgent of the CONNECT request is the same as the default userAgent,
74 // then the custom userAgent was not properly propagated and the test should fail.
75 String userAgent = request.getHeader(USER_AGENT.toString());
76 if(userAgent.equals(defaultUserAgent())) {
77 return false;
78 }
79
80 // If the authentication failed, the test should also fail.
6981 String authorization = request.getHeader(PROXY_AUTHORIZATION.toString());
7082 if (authorization == null) {
7183 response.setStatus(HttpServletResponse.SC_PROXY_AUTHENTICATION_REQUIRED);
7284 response.setHeader(PROXY_AUTHENTICATE.toString(), "Basic realm=\"Fake Realm\"");
7385 return false;
74 } else if (authorization.equals("Basic am9obmRvZTpwYXNz")) {
86 }
87 else if (authorization.equals("Basic am9obmRvZTpwYXNz")) {
7588 return true;
7689 }
7790 response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
97110 String targetUrl = "https://localhost:" + httpPort + "/foo/bar";
98111 Request request = get(targetUrl)
99112 .setProxyServer(proxyServer("127.0.0.1", proxyPort).setRealm(realm(AuthScheme.BASIC, "johndoe", "pass")))
113 .setHeader("user-agent", CUSTOM_USER_AGENT)
100114 // .setRealm(realm(AuthScheme.BASIC, "user", "passwd"))
101115 .build();
102116 Future<Response> responseFuture = client.executeRequest(request);
106120 Assert.assertEquals("/foo/bar", response.getHeader("X-pathInfo"));
107121 }
108122 }
109 }
123 }
6969 private static class Head302handler extends AbstractHandler {
7070 public void handle(String s, org.eclipse.jetty.server.Request r, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
7171 if ("HEAD".equalsIgnoreCase(request.getMethod())) {
72 response.setStatus(HttpServletResponse.SC_FOUND); // 302
73 response.setHeader("Location", request.getPathInfo() + "_moved");
74 } else if ("GET".equalsIgnoreCase(request.getMethod())) {
72 // See https://github.com/AsyncHttpClient/async-http-client/issues/1728#issuecomment-700007980
73 // When setFollowRedirect == TRUE, a follow-up request to a HEAD request will also be a HEAD.
74 // This will cause an infinite loop, which will error out once the maximum amount of redirects is hit (default 5).
75 // Instead, we (arbitrarily) choose to allow for 3 redirects and then return a 200.
76 if(request.getRequestURI().endsWith("_moved_moved_moved")) {
77 response.setStatus(HttpServletResponse.SC_OK);
78 } else {
79 response.setStatus(HttpServletResponse.SC_FOUND); // 302
80 response.setHeader("Location", request.getPathInfo() + "_moved");
81 }
82 } else if ("GET".equalsIgnoreCase(request.getMethod()) ) {
7583 response.setStatus(HttpServletResponse.SC_OK);
7684 } else {
7785 response.setStatus(HttpServletResponse.SC_FORBIDDEN);
5252 socket.shutdownInput();
5353 if (req.endsWith("MultiEnt")) {
5454 OutputStreamWriter outputStreamWriter = new OutputStreamWriter(socket.getOutputStream());
55 outputStreamWriter.append("HTTP/1.0 200 OK\n" + "Connection: close\n" + "Content-Type: text/plain; charset=iso-8859-1\n" + "Content-Length: 2\n"
56 + "Content-Length: 1\n" + "\n0\n");
55 outputStreamWriter.append("HTTP/1.0 200 OK\n" + "Connection: close\n" + "Content-Type: text/plain; charset=iso-8859-1\n" + "X-Duplicated-Header: 2\n"
56 + "X-Duplicated-Header: 1\n" + "\n0\n");
5757 outputStreamWriter.flush();
5858 socket.shutdownOutput();
5959 } else if (req.endsWith("MultiOther")) {
147147 public State onHeadersReceived(HttpHeaders response) {
148148 try {
149149 int i = 0;
150 for (String header : response.getAll(CONTENT_LENGTH)) {
150 for (String header : response.getAll("X-Duplicated-Header")) {
151151 clHeaders[i++] = header;
152152 }
153153 } finally {
0 package org.asynchttpclient.netty;
1
2 import org.asynchttpclient.DefaultAsyncHttpClient;
3 import org.asynchttpclient.DefaultAsyncHttpClientConfig;
4 import org.asynchttpclient.RequestBuilder;
5 import org.testng.annotations.BeforeTest;
6 import org.testng.annotations.Test;
7
8 import java.io.IOException;
9 import java.io.InputStream;
10 import java.io.OutputStream;
11 import java.net.ServerSocket;
12 import java.net.Socket;
13 import java.net.SocketException;
14 import java.util.Arrays;
15 import java.util.concurrent.Exchanger;
16 import java.util.concurrent.ExecutionException;
17 import java.util.concurrent.TimeoutException;
18 import java.util.function.Consumer;
19
20 import static org.hamcrest.CoreMatchers.instanceOf;
21 import static org.hamcrest.CoreMatchers.is;
22 import static org.hamcrest.MatcherAssert.assertThat;
23 import static org.hamcrest.Matchers.not;
24 import static org.testng.Assert.assertTrue;
25
26 public class NettyConnectionResetByPeerTest {
27
28 private String resettingServerAddress;
29
30 @BeforeTest
31 public void setUp() {
32 resettingServerAddress = createResettingServer();
33 }
34
35 @Test
36 public void testAsyncHttpClientConnectionResetByPeer() throws InterruptedException {
37 try {
38 DefaultAsyncHttpClientConfig config = new DefaultAsyncHttpClientConfig.Builder()
39 .setRequestTimeout(1500)
40 .build();
41 new DefaultAsyncHttpClient(config).executeRequest(
42 new RequestBuilder("GET").setUrl(resettingServerAddress)
43 )
44 .get();
45 } catch (ExecutionException e) {
46 Throwable ex = e.getCause();
47 assertThat(ex, is(instanceOf(IOException.class)));
48 }
49 }
50
51 private static String createResettingServer() {
52 return createServer(sock -> {
53 try (Socket socket = sock) {
54 socket.setSoLinger(true, 0);
55 InputStream inputStream = socket.getInputStream();
56 //to not eliminate read
57 OutputStream os = new OutputStream() {
58 @Override
59 public void write(int b) {
60 // Do nothing
61 }
62 };
63 os.write(startRead(inputStream));
64 } catch (IOException e) {
65 throw new RuntimeException(e);
66 }
67 });
68 }
69
70 private static String createServer(Consumer<Socket> handler) {
71 Exchanger<Integer> portHolder = new Exchanger<>();
72 Thread t = new Thread(() -> {
73 try (ServerSocket ss = new ServerSocket(0)) {
74 portHolder.exchange(ss.getLocalPort());
75 while (true) {
76 handler.accept(ss.accept());
77 }
78 } catch (Exception e) {
79 if (e instanceof InterruptedException) {
80 Thread.currentThread()
81 .interrupt();
82 }
83 throw new RuntimeException(e);
84 }
85 });
86 t.setDaemon(true);
87 t.start();
88 return tryGetAddress(portHolder);
89 }
90
91 private static String tryGetAddress(Exchanger<Integer> portHolder) {
92 try {
93 return "http://localhost:" + portHolder.exchange(0);
94 } catch (InterruptedException e) {
95 Thread.currentThread()
96 .interrupt();
97 throw new RuntimeException(e);
98 }
99 }
100
101 private static byte[] startRead(InputStream inputStream) throws IOException {
102 byte[] buffer = new byte[4];
103 int length = inputStream.read(buffer);
104 return Arrays.copyOf(buffer, length);
105 }
106
107 }
0 /*
1 * Copyright (c) 2010-2012 Sonatype, Inc. All rights reserved.
2 *
3 * This program is licensed to you under the Apache License Version 2.0,
4 * and you may not use this file except in compliance with the Apache License Version 2.0.
5 * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
6 *
7 * Unless required by applicable law or agreed to in writing,
8 * software distributed under the Apache License Version 2.0 is distributed on an
9 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
11 */
12 package org.asynchttpclient.proxy;
13
14 import io.netty.handler.codec.http.DefaultHttpHeaders;
15 import org.asynchttpclient.AbstractBasicTest;
16 import org.asynchttpclient.AsyncHttpClient;
17 import org.asynchttpclient.AsyncHttpClientConfig;
18 import org.asynchttpclient.Response;
19 import org.asynchttpclient.request.body.generator.ByteArrayBodyGenerator;
20 import org.asynchttpclient.test.EchoHandler;
21 import org.asynchttpclient.util.HttpConstants;
22 import org.eclipse.jetty.proxy.ConnectHandler;
23 import org.eclipse.jetty.server.Request;
24 import org.eclipse.jetty.server.Server;
25 import org.eclipse.jetty.server.ServerConnector;
26 import org.eclipse.jetty.server.handler.AbstractHandler;
27 import org.testng.annotations.AfterClass;
28 import org.testng.annotations.BeforeClass;
29 import org.testng.annotations.Test;
30
31 import javax.servlet.ServletException;
32 import javax.servlet.http.HttpServletRequest;
33 import javax.servlet.http.HttpServletResponse;
34 import java.io.IOException;
35
36 import static org.asynchttpclient.Dsl.*;
37 import static org.asynchttpclient.test.TestUtils.*;
38 import static org.testng.Assert.assertEquals;
39
40 /**
41 * Proxy usage tests.
42 */
43 public class CustomHeaderProxyTest extends AbstractBasicTest {
44
45 private Server server2;
46
47 private final String customHeaderName = "Custom-Header";
48 private final String customHeaderValue = "Custom-Value";
49
50 public AbstractHandler configureHandler() throws Exception {
51 return new ProxyHandler(customHeaderName, customHeaderValue);
52 }
53
54 @BeforeClass(alwaysRun = true)
55 public void setUpGlobal() throws Exception {
56 server = new Server();
57 ServerConnector connector = addHttpConnector(server);
58 server.setHandler(configureHandler());
59 server.start();
60 port1 = connector.getLocalPort();
61
62 server2 = new Server();
63 ServerConnector connector2 = addHttpsConnector(server2);
64 server2.setHandler(new EchoHandler());
65 server2.start();
66 port2 = connector2.getLocalPort();
67
68 logger.info("Local HTTP server started successfully");
69 }
70
71 @AfterClass(alwaysRun = true)
72 public void tearDownGlobal() throws Exception {
73 server.stop();
74 server2.stop();
75 }
76
77 @Test
78 public void testHttpProxy() throws Exception {
79 AsyncHttpClientConfig config = config()
80 .setFollowRedirect(true)
81 .setProxyServer(
82 proxyServer("localhost", port1)
83 .setCustomHeaders((req) -> new DefaultHttpHeaders().add(customHeaderName, customHeaderValue))
84 .build()
85 )
86 .setUseInsecureTrustManager(true)
87 .build();
88 try (AsyncHttpClient asyncHttpClient = asyncHttpClient(config)) {
89 Response r = asyncHttpClient.executeRequest(post(getTargetUrl2()).setBody(new ByteArrayBodyGenerator(LARGE_IMAGE_BYTES))).get();
90 assertEquals(r.getStatusCode(), 200);
91 }
92 }
93
94 public static class ProxyHandler extends ConnectHandler {
95 String customHeaderName;
96 String customHeaderValue;
97
98 public ProxyHandler(String customHeaderName, String customHeaderValue) {
99 this.customHeaderName = customHeaderName;
100 this.customHeaderValue = customHeaderValue;
101 }
102
103 @Override
104 public void handle(String s, Request r, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
105 if (HttpConstants.Methods.CONNECT.equalsIgnoreCase(request.getMethod())) {
106 if (request.getHeader(customHeaderName).equals(customHeaderValue)) {
107 response.setStatus(HttpServletResponse.SC_OK);
108 super.handle(s, r, request, response);
109 } else {
110 response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
111 r.setHandled(true);
112 }
113 } else {
114 super.handle(s, r, request, response);
115 }
116 }
117 }
118 }
11 <parent>
22 <groupId>org.asynchttpclient</groupId>
33 <artifactId>async-http-client-project</artifactId>
4 <version>2.12.2</version>
4 <version>2.12.3</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.12.2</version>
4 <version>2.12.3</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.12.2</version>
20 <version>2.12.3</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.12.2</version>
4 <version>2.12.3</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.12.2</version>
4 <version>2.12.3</version>
55 </parent>
66 <modelVersion>4.0.0</modelVersion>
77 <artifactId>async-http-client-extras-registry</artifactId>
33 <parent>
44 <artifactId>async-http-client-extras-parent</artifactId>
55 <groupId>org.asynchttpclient</groupId>
6 <version>2.12.2</version>
6 <version>2.12.3</version>
77 </parent>
88
99 <artifactId>async-http-client-extras-retrofit2</artifactId>
22 <parent>
33 <artifactId>async-http-client-extras-parent</artifactId>
44 <groupId>org.asynchttpclient</groupId>
5 <version>2.12.2</version>
5 <version>2.12.3</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.12.2</version>
5 <version>2.12.3</version>
66 </parent>
77 <artifactId>async-http-client-extras-rxjava2</artifactId>
88 <name>Asynchronous Http Client RxJava2 Extras</name>
22 <parent>
33 <artifactId>async-http-client-extras-parent</artifactId>
44 <groupId>org.asynchttpclient</groupId>
5 <version>2.12.2</version>
5 <version>2.12.3</version>
66 </parent>
77 <artifactId>async-http-client-extras-simple</artifactId>
88 <name>Asynchronous Http Simple Client</name>
33 <parent>
44 <artifactId>async-http-client-extras-parent</artifactId>
55 <groupId>org.asynchttpclient</groupId>
6 <version>2.12.2</version>
6 <version>2.12.3</version>
77 </parent>
88
99 <artifactId>async-http-client-extras-typesafe-config</artifactId>
11 <parent>
22 <groupId>org.asynchttpclient</groupId>
33 <artifactId>async-http-client-project</artifactId>
4 <version>2.12.2</version>
4 <version>2.12.3</version>
55 </parent>
66 <modelVersion>4.0.0</modelVersion>
77 <artifactId>async-http-client-netty-utils</artifactId>
33
44 <groupId>org.asynchttpclient</groupId>
55 <artifactId>async-http-client-project</artifactId>
6 <version>2.12.2</version>
6 <version>2.12.3</version>
77 <packaging>pom</packaging>
88
99 <name>Asynchronous Http Client Project</name>
3333 <connection>scm:git:git@github.com:AsyncHttpClient/async-http-client.git</connection>
3434 <developerConnection>scm:git:git@github.com:AsyncHttpClient/async-http-client.git</developerConnection>
3535 <url>https://github.com/AsyncHttpClient/async-http-client/tree/master</url>
36 <tag>async-http-client-project-2.12.2</tag>
36 <tag>async-http-client-project-2.12.3</tag>
3737 </scm>
3838
3939 <distributionManagement>
465465 <surefire.redirectTestOutputToFile>true</surefire.redirectTestOutputToFile>
466466 <source.property>1.8</source.property>
467467 <target.property>1.8</target.property>
468 <netty.version>4.1.53.Final</netty.version>
468 <netty.version>4.1.60.Final</netty.version>
469469 <slf4j.version>1.7.30</slf4j.version>
470470 <reactive-streams.version>1.0.3</reactive-streams.version>
471471 <activation.version>1.2.2</activation.version>