11/*
2- * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 2013, 2022 Oracle and/or its affiliates. All rights reserved.
33 *
44 * This program and the accompanying materials are made available under the
55 * terms of the Eclipse Public License v. 2.0, which is available at
1616
1717package org .glassfish .jersey .jetty .connector ;
1818
19+ import static org .hamcrest .CoreMatchers .instanceOf ;
20+ import static org .junit .Assert .assertEquals ;
21+ import static org .junit .Assert .assertThat ;
22+ import static org .junit .Assert .assertTrue ;
23+ import static org .junit .Assert .fail ;
24+
1925import java .net .URI ;
26+ import java .nio .charset .StandardCharsets ;
27+ import java .util .concurrent .TimeUnit ;
2028import java .util .concurrent .TimeoutException ;
2129import java .util .logging .Logger ;
2230
31+ import javax .ws .rs .DefaultValue ;
2332import javax .ws .rs .GET ;
2433import javax .ws .rs .Path ;
2534import javax .ws .rs .ProcessingException ;
35+ import javax .ws .rs .QueryParam ;
2636import javax .ws .rs .client .Client ;
2737import javax .ws .rs .client .ClientBuilder ;
2838import javax .ws .rs .client .WebTarget ;
2939import javax .ws .rs .core .Application ;
3040import javax .ws .rs .core .Response ;
41+ import javax .ws .rs .core .StreamingOutput ;
3142
43+ import org .glassfish .jersey .CommonProperties ;
3244import org .glassfish .jersey .client .ClientConfig ;
3345import org .glassfish .jersey .client .ClientProperties ;
3446import org .glassfish .jersey .logging .LoggingFeature ;
3547import org .glassfish .jersey .server .ResourceConfig ;
3648import org .glassfish .jersey .test .JerseyTest ;
37-
3849import org .junit .Test ;
39- import static org .hamcrest .CoreMatchers .instanceOf ;
40- import static org .junit .Assert .assertEquals ;
41- import static org .junit .Assert .assertThat ;
42- import static org .junit .Assert .fail ;
4350
4451/**
4552 * @author Martin Matula
@@ -65,6 +72,48 @@ public String getTimeout() {
6572 }
6673 return "GET" ;
6774 }
75+
76+ /**
77+ * Long-running streaming request
78+ *
79+ * @param count number of packets send
80+ * @param pauseMillis pause between each packets
81+ */
82+ @ GET
83+ @ Path ("stream" )
84+ public Response streamsWithDelay (@ QueryParam ("start" ) @ DefaultValue ("0" ) int startMillis , @ QueryParam ("count" ) int count ,
85+ @ QueryParam ("pauseMillis" ) int pauseMillis ) {
86+ StreamingOutput streamingOutput = streamSlowly (startMillis , count , pauseMillis );
87+
88+ return Response .ok (streamingOutput )
89+ .build ();
90+ }
91+ }
92+
93+ private static StreamingOutput streamSlowly (int startMillis , int count , int pauseMillis ) {
94+
95+ return output -> {
96+ try {
97+ TimeUnit .MILLISECONDS .sleep (startMillis );
98+ }
99+ catch (InterruptedException e ) {
100+ Thread .currentThread ().interrupt ();
101+ }
102+ output .write ("begin\n " .getBytes (StandardCharsets .UTF_8 ));
103+ output .flush ();
104+ for (int i = 0 ; i < count ; i ++) {
105+ try {
106+ TimeUnit .MILLISECONDS .sleep (pauseMillis );
107+ }
108+ catch (InterruptedException e ) {
109+ Thread .currentThread ().interrupt ();
110+ }
111+
112+ output .write (("message " + i + "\n " ).getBytes (StandardCharsets .UTF_8 ));
113+ output .flush ();
114+ }
115+ output .write ("end" .getBytes (StandardCharsets .UTF_8 ));
116+ };
68117 }
69118
70119 @ Override
@@ -121,4 +170,74 @@ public void testTimeoutInRequest() {
121170 c .close ();
122171 }
123172 }
173+
174+ /**
175+ * Test accessing an operation that is streaming slowly
176+ *
177+ * @throws ProcessingException in case of a test error.
178+ */
179+ @ Test
180+ public void testSlowlyStreamedContentDoesNotReadTimeout () throws Exception {
181+
182+ int count = 5 ;
183+ int pauseMillis = 50 ;
184+
185+ final Response response = target ("test" )
186+ .property (ClientProperties .READ_TIMEOUT , 100L )
187+ .property (CommonProperties .OUTBOUND_CONTENT_LENGTH_BUFFER_SERVER , "-1" )
188+ .path ("stream" )
189+ .queryParam ("count" , count )
190+ .queryParam ("pauseMillis" , pauseMillis )
191+ .request ().get ();
192+
193+ assertTrue (response .readEntity (String .class ).contains ("end" ));
194+ }
195+
196+ @ Test
197+ public void testSlowlyStreamedContentDoesTotalTimeout () throws Exception {
198+
199+ int count = 5 ;
200+ int pauseMillis = 50 ;
201+
202+ try {
203+ target ("test" )
204+ .property (JettyClientProperties .TOTAL_TIMEOUT , 100L )
205+ .property (CommonProperties .OUTBOUND_CONTENT_LENGTH_BUFFER_SERVER , "-1" )
206+ .path ("stream" )
207+ .queryParam ("count" , count )
208+ .queryParam ("pauseMillis" , pauseMillis )
209+ .request ().get ();
210+
211+ fail ("This operation should trigger total timeout" );
212+ } catch (ProcessingException e ) {
213+ assertEquals (TimeoutException .class , e .getCause ().getClass ());
214+ }
215+ }
216+
217+ /**
218+ * Test accessing an operation that is streaming slowly
219+ *
220+ * @throws ProcessingException in case of a test error.
221+ */
222+ @ Test
223+ public void testSlowToStartStreamedContentDoesReadTimeout () throws Exception {
224+
225+ int start = 150 ;
226+ int count = 5 ;
227+ int pauseMillis = 50 ;
228+
229+ try {
230+ target ("test" )
231+ .property (ClientProperties .READ_TIMEOUT , 100L )
232+ .property (CommonProperties .OUTBOUND_CONTENT_LENGTH_BUFFER_SERVER , "-1" )
233+ .path ("stream" )
234+ .queryParam ("start" , start )
235+ .queryParam ("count" , count )
236+ .queryParam ("pauseMillis" , pauseMillis )
237+ .request ().get ();
238+ fail ("This operation should trigger idle timeout" );
239+ } catch (ProcessingException e ) {
240+ assertEquals (TimeoutException .class , e .getCause ().getClass ());
241+ }
242+ }
124243}
0 commit comments