12
12
*/
13
13
package org .asynchttpclient .handler ;
14
14
15
- import org .apache .commons .io .IOUtils ;
16
- import org .asynchttpclient .*;
17
- import org .asynchttpclient .exception .RemotelyClosedException ;
18
- import org .asynchttpclient .handler .BodyDeferringAsyncHandler .BodyDeferringInputStream ;
19
- import org .eclipse .jetty .server .Request ;
20
- import org .eclipse .jetty .server .handler .AbstractHandler ;
21
- import org .testng .annotations .Test ;
15
+ import static io .netty .handler .codec .http .HttpHeaderNames .CONTENT_LENGTH ;
16
+ import static io .netty .handler .codec .http .HttpHeaderValues .APPLICATION_OCTET_STREAM ;
17
+ import static org .apache .commons .io .IOUtils .copy ;
18
+ import static org .asynchttpclient .Dsl .asyncHttpClient ;
19
+ import static org .asynchttpclient .Dsl .config ;
20
+ import static org .asynchttpclient .test .TestUtils .findFreePort ;
21
+ import static org .testng .Assert .assertEquals ;
22
+ import static org .testng .Assert .assertNotEquals ;
23
+ import static org .testng .Assert .assertNotNull ;
24
+ import static org .testng .Assert .assertTrue ;
22
25
23
- import javax .servlet .ServletException ;
24
- import javax .servlet .http .HttpServletRequest ;
25
- import javax .servlet .http .HttpServletResponse ;
26
26
import java .io .IOException ;
27
27
import java .io .OutputStream ;
28
28
import java .io .PipedInputStream ;
29
29
import java .io .PipedOutputStream ;
30
30
import java .nio .charset .StandardCharsets ;
31
31
import java .util .concurrent .ExecutionException ;
32
32
import java .util .concurrent .Future ;
33
+ import javax .servlet .ServletException ;
34
+ import javax .servlet .http .HttpServletRequest ;
35
+ import javax .servlet .http .HttpServletResponse ;
33
36
34
- import static io .netty .handler .codec .http .HttpHeaderNames .CONTENT_LENGTH ;
35
- import static io .netty .handler .codec .http .HttpHeaderValues .APPLICATION_OCTET_STREAM ;
36
- import static org .apache .commons .io .IOUtils .copy ;
37
- import static org .asynchttpclient .Dsl .asyncHttpClient ;
38
- import static org .asynchttpclient .Dsl .config ;
39
- import static org .asynchttpclient .test .TestUtils .findFreePort ;
40
- import static org .testng .Assert .*;
37
+ import org .apache .commons .io .IOUtils ;
38
+ import org .asynchttpclient .AbstractBasicTest ;
39
+ import org .asynchttpclient .AsyncHttpClient ;
40
+ import org .asynchttpclient .AsyncHttpClientConfig ;
41
+ import org .asynchttpclient .BoundRequestBuilder ;
42
+ import org .asynchttpclient .ListenableFuture ;
43
+ import org .asynchttpclient .Response ;
44
+ import org .asynchttpclient .exception .RemotelyClosedException ;
45
+ import org .asynchttpclient .handler .BodyDeferringAsyncHandler .BodyDeferringInputStream ;
46
+ import org .eclipse .jetty .server .Request ;
47
+ import org .eclipse .jetty .server .handler .AbstractHandler ;
48
+ import org .testng .annotations .Test ;
41
49
42
50
public class BodyDeferringAsyncHandlerTest extends AbstractBasicTest {
43
51
@@ -169,6 +177,37 @@ public void deferredInputStreamTrickWithFailure() throws Throwable {
169
177
}
170
178
}
171
179
180
+ @ Test (expectedExceptions = UnsupportedOperationException .class )
181
+ public void deferredInputStreamTrickWithCloseConnectionAndRetry () throws Throwable {
182
+ try (AsyncHttpClient client = asyncHttpClient (config ().setMaxRequestRetry (1 ).setRequestTimeout (10000 ).build ())) {
183
+ BoundRequestBuilder r = client .prepareGet (getTargetUrl ()).addHeader ("X-CLOSE-CONNECTION" , Boolean .TRUE .toString ());
184
+ PipedOutputStream pos = new PipedOutputStream ();
185
+ PipedInputStream pis = new PipedInputStream (pos );
186
+ BodyDeferringAsyncHandler bdah = new BodyDeferringAsyncHandler (pos );
187
+
188
+ Future <Response > f = r .execute (bdah );
189
+
190
+ BodyDeferringInputStream is = new BodyDeferringInputStream (f , bdah , pis );
191
+
192
+ Response resp = is .getAsapResponse ();
193
+ assertNotNull (resp );
194
+ assertEquals (resp .getStatusCode (), HttpServletResponse .SC_OK );
195
+ assertEquals (resp .getHeader (CONTENT_LENGTH ), String .valueOf (CONTENT_LENGTH_VALUE ));
196
+ // "consume" the body, but our code needs input stream
197
+ CountingOutputStream cos = new CountingOutputStream ();
198
+ try {
199
+ try {
200
+ copy (is , cos );
201
+ } finally {
202
+ is .close ();
203
+ cos .close ();
204
+ }
205
+ } catch (IOException e ) {
206
+ throw e .getCause ();
207
+ }
208
+ }
209
+ }
210
+
172
211
@ Test (expectedExceptions = IOException .class )
173
212
public void testConnectionRefused () throws IOException , InterruptedException {
174
213
int newPortWithoutAnyoneListening = findFreePort ();
@@ -214,6 +253,7 @@ public void handle(String pathInContext, Request request, HttpServletRequest htt
214
253
215
254
httpResponse .flushBuffer ();
216
255
256
+ final boolean wantConnectionClose = httpRequest .getHeader ("X-CLOSE-CONNECTION" ) != null ;
217
257
final boolean wantFailure = httpRequest .getHeader ("X-FAIL-TRANSFER" ) != null ;
218
258
final boolean wantSlow = httpRequest .getHeader ("X-SLOW" ) != null ;
219
259
@@ -229,12 +269,17 @@ public void handle(String pathInContext, Request request, HttpServletRequest htt
229
269
}
230
270
}
231
271
232
- if (wantFailure && i > CONTENT_LENGTH_VALUE / 2 ) {
233
- // kaboom
234
- // yes, response is committed, but Jetty does aborts and
235
- // drops connection
236
- httpResponse .sendError (500 );
237
- break ;
272
+ if (i > CONTENT_LENGTH_VALUE / 2 ) {
273
+ if (wantFailure ) {
274
+ // kaboom
275
+ // yes, response is committed, but Jetty does aborts and
276
+ // drops connection
277
+ httpResponse .sendError (500 );
278
+ break ;
279
+ } else if (wantConnectionClose ) {
280
+ // kaboom^2
281
+ httpResponse .getOutputStream ().close ();
282
+ }
238
283
}
239
284
}
240
285
0 commit comments