New upstream version 2.0.17
Emmanuel Bourg
5 years ago
1 | 1 | <parent> |
2 | 2 | <groupId>org.asynchttpclient</groupId> |
3 | 3 | <artifactId>async-http-client-project</artifactId> |
4 | <version>2.0.16</version> | |
4 | <version>2.0.17</version> | |
5 | 5 | </parent> |
6 | 6 | <modelVersion>4.0.0</modelVersion> |
7 | 7 | <artifactId>async-http-client</artifactId> |
35 | 35 | /** |
36 | 36 | * The Request class can be used to construct HTTP request: |
37 | 37 | * <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(); | |
43 | 45 | * </pre></blockquote> |
44 | 46 | */ |
45 | 47 | public interface Request { |
46 | 48 | |
47 | 49 | /** |
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.) | |
51 | 51 | */ |
52 | 52 | String getMethod(); |
53 | 53 | |
54 | /** | |
55 | * | |
56 | * @return the uri | |
57 | */ | |
54 | 58 | Uri getUri(); |
55 | 59 | |
60 | /** | |
61 | * @return the url (the uri's String form) | |
62 | */ | |
56 | 63 | String getUrl(); |
57 | 64 | |
58 | 65 | /** |
59 | * Return the InetAddress to override | |
60 | * | |
61 | * @return the InetAddress | |
66 | * @return the InetAddress to be used to bypass uri's hostname resolution | |
62 | 67 | */ |
63 | 68 | InetAddress getAddress(); |
64 | 69 | |
70 | /** | |
71 | * @return the local address to bind from | |
72 | */ | |
65 | 73 | InetAddress getLocalAddress(); |
66 | 74 | |
67 | 75 | /** |
68 | * Return the current set of Headers. | |
69 | * | |
70 | * @return a {@link HttpHeaders} contains headers. | |
76 | * @return the HTTP headers | |
71 | 77 | */ |
72 | 78 | HttpHeaders getHeaders(); |
73 | 79 | |
74 | 80 | /** |
75 | * Return cookies. | |
76 | * | |
77 | * @return an unmodifiable Collection of Cookies | |
81 | * @return the HTTP cookies | |
78 | 82 | */ |
79 | 83 | List<Cookie> getCookies(); |
80 | 84 | |
81 | 85 | /** |
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) | |
85 | 87 | */ |
86 | 88 | byte[] getByteData(); |
87 | 89 | |
88 | 90 | /** |
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) | |
90 | 92 | */ |
91 | 93 | List<byte[]> getCompositeByteData(); |
92 | 94 | |
93 | 95 | /** |
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) | |
97 | 97 | */ |
98 | 98 | String getStringData(); |
99 | 99 | |
100 | 100 | /** |
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) | |
104 | 102 | */ |
105 | 103 | ByteBuffer getByteBufferData(); |
106 | 104 | |
107 | 105 | /** |
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) | |
111 | 107 | */ |
112 | 108 | InputStream getStreamData(); |
113 | 109 | |
114 | 110 | /** |
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) | |
118 | 112 | */ |
119 | 113 | BodyGenerator getBodyGenerator(); |
120 | 114 | |
121 | 115 | /** |
122 | * Return the current form parameters. | |
123 | * | |
124 | * @return the form parameters. | |
116 | * @return the request's form parameters | |
125 | 117 | */ |
126 | 118 | List<Param> getFormParams(); |
127 | 119 | |
128 | 120 | /** |
129 | * Return the current {@link Part} | |
130 | * | |
131 | * @return the current {@link Part} | |
121 | * @return the multipart parts | |
132 | 122 | */ |
133 | 123 | List<Part> getBodyParts(); |
134 | 124 | |
135 | 125 | /** |
136 | * Return the virtual host value. | |
137 | * | |
138 | * @return the virtual host value. | |
126 | * @return the virtual host to connect to | |
139 | 127 | */ |
140 | 128 | String getVirtualHost(); |
141 | 129 | |
142 | 130 | /** |
143 | * Return the query params. | |
144 | * | |
145 | * @return the query parameters | |
131 | * @return the query params resolved from the url/uri | |
146 | 132 | */ |
147 | 133 | List<Param> getQueryParams(); |
148 | 134 | |
149 | 135 | /** |
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) | |
153 | 137 | */ |
154 | 138 | ProxyServer getProxyServer(); |
155 | 139 | |
156 | 140 | /** |
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) | |
160 | 142 | */ |
161 | 143 | Realm getRealm(); |
162 | 144 | |
163 | 145 | /** |
164 | * Return the {@link File} to upload. | |
165 | * | |
166 | * @return the {@link File} to upload. | |
146 | * @return the file to be uploaded | |
167 | 147 | */ |
168 | 148 | File getFile(); |
169 | 149 | |
170 | 150 | /** |
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". | |
174 | 152 | */ |
175 | 153 | Boolean getFollowRedirect(); |
176 | 154 | |
177 | 155 | /** |
178 | * Overrides the config default value | |
179 | * @return the request timeout | |
156 | * @return the request timeout. Non zero values means "override config value". | |
180 | 157 | */ |
181 | 158 | int getRequestTimeout(); |
182 | 159 | |
183 | 160 | /** |
184 | * Return the HTTP Range header value, or | |
185 | * | |
186 | 161 | * @return the range header value, or 0 is not set. |
187 | 162 | */ |
188 | 163 | long getRangeOffset(); |
189 | 164 | |
190 | 165 | /** |
191 | * Return the charset value used when decoding the request's body. | |
192 | * | |
193 | 166 | * @return the charset value used when decoding the request's body. |
194 | 167 | */ |
195 | 168 | Charset getCharset(); |
196 | 169 | |
170 | /** | |
171 | * @return the strategy to compute ChannelPool's keys | |
172 | */ | |
197 | 173 | ChannelPoolPartitioning getChannelPoolPartitioning(); |
198 | 174 | |
175 | /** | |
176 | * @return the NameResolver to be used to resolve hostnams's IP | |
177 | */ | |
199 | 178 | NameResolver<InetAddress> getNameResolver(); |
200 | 179 | } |
11 | 11 | * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. |
12 | 12 | */ |
13 | 13 | package org.asynchttpclient.netty.channel; |
14 | ||
15 | import java.util.concurrent.atomic.AtomicBoolean; | |
14 | 16 | |
15 | 17 | import io.netty.channel.Channel; |
16 | 18 | import io.netty.channel.ChannelId; |
28 | 30 | |
29 | 31 | private static final AttributeKey<Object> DEFAULT_ATTRIBUTE = AttributeKey.valueOf("default"); |
30 | 32 | private static final AttributeKey<ChannelId> CHANNEL_ID_ATTRIBUTE = AttributeKey.valueOf("channelId"); |
33 | private static final AttributeKey<AtomicBoolean> INACTIVE_TOKEN_ATTRIBUTE = AttributeKey.valueOf("inactiveToken"); | |
31 | 34 | |
32 | 35 | public static Object getAttribute(Channel channel) { |
33 | 36 | Attribute<Object> attr = channel.attr(DEFAULT_ATTRIBUTE); |
44 | 47 | |
45 | 48 | public static boolean isChannelValid(Channel channel) { |
46 | 49 | 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); | |
47 | 58 | } |
48 | 59 | |
49 | 60 | public static ChannelId getChannelId(Channel channel) { |
94 | 94 | |
95 | 95 | public void onSuccess(Channel channel, InetSocketAddress remoteAddress) { |
96 | 96 | |
97 | Channels.setInactiveToken(channel); | |
98 | ||
97 | 99 | TimeoutsHolder timeoutsHolder = future.getTimeoutsHolder(); |
98 | 100 | |
99 | 101 | if (futureIsAlreadyCancelled(channel)) { |
197 | 197 | |
198 | 198 | @Override |
199 | 199 | public void handleException(NettyResponseFuture<?> future, Throwable e) { |
200 | logger.warn("onError {}", e); | |
200 | logger.warn("onError", e); | |
201 | 201 | |
202 | 202 | try { |
203 | 203 | WebSocketUpgradeHandler h = (WebSocketUpgradeHandler) future.getAsyncHandler(); |
+1
-1
67 | 67 | Realm proxyRealm = future.getProxyRealm(); |
68 | 68 | |
69 | 69 | 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"); | |
71 | 71 | return false; |
72 | 72 | } |
73 | 73 |
+1
-1
63 | 63 | HttpRequest httpRequest) { |
64 | 64 | |
65 | 65 | 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"); | |
67 | 67 | return false; |
68 | 68 | } |
69 | 69 |
18 | 18 | import java.net.InetAddress; |
19 | 19 | import java.net.InetSocketAddress; |
20 | 20 | import java.util.List; |
21 | import java.util.concurrent.RejectedExecutionException; | |
21 | 22 | |
22 | 23 | import org.asynchttpclient.AsyncHandler; |
23 | 24 | import org.asynchttpclient.AsyncHttpClientConfig; |
65 | 66 | |
66 | 67 | try { |
67 | 68 | connect0(bootstrap, connectListener, remoteAddress); |
68 | } catch (Throwable e) { | |
69 | // workaround for https://github.com/netty/netty/issues/5387 | |
69 | } catch (RejectedExecutionException e) { | |
70 | 70 | if (clientState.isClosed()) { |
71 | 71 | connectListener.onFailure(null, e); |
72 | 72 | } else { |
19 | 19 | import static org.asynchttpclient.util.MiscUtils.*; |
20 | 20 | import static org.asynchttpclient.ws.WebSocketUtils.getKey; |
21 | 21 | import io.netty.buffer.ByteBuf; |
22 | import io.netty.buffer.Unpooled; | |
22 | 23 | import io.netty.handler.codec.http.DefaultFullHttpRequest; |
23 | 24 | import io.netty.handler.codec.http.DefaultHttpRequest; |
24 | 25 | import io.netty.handler.codec.http.HttpHeaders; |
146 | 147 | nettyRequest = new NettyRequest(httpRequest, null); |
147 | 148 | |
148 | 149 | } else if (body == null) { |
149 | httpRequest = new DefaultFullHttpRequest(httpVersion, method, requestUri); | |
150 | httpRequest = new DefaultFullHttpRequest(httpVersion, method, requestUri, Unpooled.EMPTY_BUFFER); | |
150 | 151 | nettyRequest = new NettyRequest(httpRequest, null); |
151 | 152 | |
152 | 153 | } else { |
404 | 404 | } |
405 | 405 | |
406 | 406 | 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 | } | |
413 | 415 | } |
414 | 416 | } |
415 | 417 |
16 | 16 | import io.netty.handler.ssl.SslContext; |
17 | 17 | import io.netty.handler.ssl.SslContextBuilder; |
18 | 18 | import io.netty.handler.ssl.SslProvider; |
19 | import io.netty.handler.ssl.util.InsecureTrustManagerFactory; | |
20 | 19 | |
21 | 20 | import javax.net.ssl.SSLEngine; |
22 | 21 | import javax.net.ssl.SSLException; |
+105
-0
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 | }⏎ |
24 | 24 | |
25 | 25 | protected void configureSslEngine(SSLEngine sslEngine, AsyncHttpClientConfig config) { |
26 | 26 | 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); | |
32 | 30 | |
33 | 31 | if (isNonEmpty(config.getEnabledProtocols())) |
34 | 32 | sslEngine.setEnabledProtocols(config.getEnabledProtocols()); |
11 | 11 | org.asynchttpclient.compressionEnforced=false |
12 | 12 | org.asynchttpclient.userAgent=AHC/2.0 |
13 | 13 | 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 | |
15 | 15 | org.asynchttpclient.useProxySelector=false |
16 | 16 | org.asynchttpclient.useProxyProperties=false |
17 | 17 | org.asynchttpclient.validateResponseHeaders=true |
+57
-27
33 | 33 | |
34 | 34 | public class MultipartBodyTest { |
35 | 35 | |
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); | |
41 | 43 | } |
44 | PARTS.add(new ByteArrayPart("baPart", "testMultiPart".getBytes(UTF_8), "application/test", UTF_8, "fileName")); | |
45 | PARTS.add(new StringPart("stringPart", "testString")); | |
42 | 46 | } |
43 | 47 | |
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 { | |
53 | 49 | final ClassLoader cl = MultipartBodyTest.class.getClassLoader(); |
54 | 50 | final URL url = cl.getResource("textfile.txt"); |
55 | 51 | assertNotNull(url); |
56 | 52 | return new File(url.toURI()); |
57 | 53 | } |
58 | 54 | |
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 | } | |
65 | 64 | } |
66 | 65 | |
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); | |
72 | 68 | } |
73 | 69 | |
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 | } | |
75 | 79 | |
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); | |
77 | 107 | final AtomicLong transferred = new AtomicLong(); |
78 | 108 | |
79 | 109 | WritableByteChannel mockChannel = new WritableByteChannel() { |
1 | 1 | <parent> |
2 | 2 | <groupId>org.asynchttpclient</groupId> |
3 | 3 | <artifactId>async-http-client-project</artifactId> |
4 | <version>2.0.16</version> | |
4 | <version>2.0.17</version> | |
5 | 5 | </parent> |
6 | 6 | <modelVersion>4.0.0</modelVersion> |
7 | 7 | <artifactId>async-http-client-example</artifactId> |
1 | 1 | <parent> |
2 | 2 | <groupId>org.asynchttpclient</groupId> |
3 | 3 | <artifactId>async-http-client-extras-parent</artifactId> |
4 | <version>2.0.16</version> | |
4 | <version>2.0.17</version> | |
5 | 5 | </parent> |
6 | 6 | <modelVersion>4.0.0</modelVersion> |
7 | 7 | <artifactId>async-http-client-extras-guava</artifactId> |
17 | 17 | <parent> |
18 | 18 | <artifactId>async-http-client-extras-parent</artifactId> |
19 | 19 | <groupId>org.asynchttpclient</groupId> |
20 | <version>2.0.16</version> | |
20 | <version>2.0.17</version> | |
21 | 21 | </parent> |
22 | 22 | <artifactId>async-http-client-extras-jdeferred</artifactId> |
23 | 23 | <name>Asynchronous Http Client JDeferred Extras</name> |
1 | 1 | <parent> |
2 | 2 | <groupId>org.asynchttpclient</groupId> |
3 | 3 | <artifactId>async-http-client-project</artifactId> |
4 | <version>2.0.16</version> | |
4 | <version>2.0.17</version> | |
5 | 5 | </parent> |
6 | 6 | <modelVersion>4.0.0</modelVersion> |
7 | 7 | <artifactId>async-http-client-extras-parent</artifactId> |
1 | 1 | <parent> |
2 | 2 | <groupId>org.asynchttpclient</groupId> |
3 | 3 | <artifactId>async-http-client-extras-parent</artifactId> |
4 | <version>2.0.16</version> | |
4 | <version>2.0.17</version> | |
5 | 5 | </parent> |
6 | 6 | <modelVersion>4.0.0</modelVersion> |
7 | 7 | <artifactId>async-http-client-extras-registry</artifactId> |
2 | 2 | <parent> |
3 | 3 | <artifactId>async-http-client-extras-parent</artifactId> |
4 | 4 | <groupId>org.asynchttpclient</groupId> |
5 | <version>2.0.16</version> | |
5 | <version>2.0.17</version> | |
6 | 6 | </parent> |
7 | 7 | <artifactId>async-http-client-extras-rxjava</artifactId> |
8 | 8 | <name>Asynchronous Http Client RxJava Extras</name> |
2 | 2 | <parent> |
3 | 3 | <artifactId>async-http-client-extras-parent</artifactId> |
4 | 4 | <groupId>org.asynchttpclient</groupId> |
5 | <version>2.0.16</version> | |
5 | <version>2.0.17</version> | |
6 | 6 | </parent> |
7 | 7 | <artifactId>async-http-client-extras-simple</artifactId> |
8 | 8 | <name>Asynchronous Http Simple Client</name> |
19 | 19 | <parent> |
20 | 20 | <groupId>org.asynchttpclient</groupId> |
21 | 21 | <artifactId>netty-bp</artifactId> |
22 | <version>2.0.16</version> | |
22 | <version>2.0.17</version> | |
23 | 23 | </parent> |
24 | 24 | |
25 | 25 | <artifactId>netty-codec-dns</artifactId> |
1 | 1 | <parent> |
2 | 2 | <groupId>org.asynchttpclient</groupId> |
3 | 3 | <artifactId>async-http-client-project</artifactId> |
4 | <version>2.0.16</version> | |
4 | <version>2.0.17</version> | |
5 | 5 | </parent> |
6 | 6 | <modelVersion>4.0.0</modelVersion> |
7 | 7 | <artifactId>netty-bp</artifactId> |
19 | 19 | <parent> |
20 | 20 | <groupId>org.asynchttpclient</groupId> |
21 | 21 | <artifactId>netty-bp</artifactId> |
22 | <version>2.0.16</version> | |
22 | <version>2.0.17</version> | |
23 | 23 | </parent> |
24 | 24 | |
25 | 25 | <artifactId>netty-resolver</artifactId> |
8 | 8 | <parent> |
9 | 9 | <groupId>org.asynchttpclient</groupId> |
10 | 10 | <artifactId>netty-bp</artifactId> |
11 | <version>2.0.16</version> | |
11 | <version>2.0.17</version> | |
12 | 12 | </parent> |
13 | 13 | |
14 | 14 | <artifactId>netty-resolver-dns</artifactId> |
1 | 1 | <parent> |
2 | 2 | <groupId>org.asynchttpclient</groupId> |
3 | 3 | <artifactId>async-http-client-project</artifactId> |
4 | <version>2.0.16</version> | |
4 | <version>2.0.17</version> | |
5 | 5 | </parent> |
6 | 6 | <modelVersion>4.0.0</modelVersion> |
7 | 7 | <artifactId>async-http-client-netty-utils</artifactId> |
8 | 8 | <groupId>org.asynchttpclient</groupId> |
9 | 9 | <artifactId>async-http-client-project</artifactId> |
10 | 10 | <name>Asynchronous Http Client Project</name> |
11 | <version>2.0.16</version> | |
11 | <version>2.0.17</version> | |
12 | 12 | <packaging>pom</packaging> |
13 | 13 | <description> |
14 | 14 | The Async Http Client (AHC) library's purpose is to allow Java |
373 | 373 | <surefire.redirectTestOutputToFile>true</surefire.redirectTestOutputToFile> |
374 | 374 | <source.property>1.8</source.property> |
375 | 375 | <target.property>1.8</target.property> |
376 | <netty.version>4.0.41.Final</netty.version> | |
376 | <netty.version>4.0.42.Final</netty.version> | |
377 | 377 | <slf4j.version>1.7.21</slf4j.version> |
378 | 378 | <logback.version>1.1.7</logback.version> |
379 | 379 | <testng.version>6.9.10</testng.version> |