@@ -101,7 +101,86 @@ public void testRequestResponseStreaming() throws InterruptedException {
101101 final String url = "/stream/" ;
102102
103103 final ToXContent [] chunks = newChunks (responseString );
104- final HttpServerTransport .Dispatcher dispatcher = new HttpServerTransport .Dispatcher () {
104+ final HttpServerTransport .Dispatcher dispatcher = createStreamingDispatcher (url , responseString );
105+
106+ try (
107+ ReactorNetty4HttpServerTransport transport = new ReactorNetty4HttpServerTransport (
108+ Settings .EMPTY ,
109+ networkService ,
110+ bigArrays ,
111+ threadPool ,
112+ xContentRegistry (),
113+ dispatcher ,
114+ clusterSettings ,
115+ new SharedGroupFactory (Settings .EMPTY ),
116+ NoopTracer .INSTANCE
117+ )
118+ ) {
119+ transport .start ();
120+ final TransportAddress remoteAddress = randomFrom (transport .boundAddress ().boundAddresses ());
121+
122+ try (ReactorHttpClient client = ReactorHttpClient .create (false )) {
123+ HttpRequest request = new DefaultHttpRequest (HttpVersion .HTTP_1_1 , HttpMethod .GET , url );
124+ final FullHttpResponse response = client .stream (remoteAddress .address (), request , Arrays .stream (chunks ));
125+ try {
126+ assertThat (response .status (), equalTo (HttpResponseStatus .OK ));
127+ byte [] bytes = new byte [response .content ().readableBytes ()];
128+ response .content ().readBytes (bytes );
129+ assertThat (new String (bytes , StandardCharsets .UTF_8 ), equalTo (Arrays .stream (newChunks (responseString )).map (s -> {
130+ try (XContentBuilder builder = XContentType .JSON .contentBuilder ()) {
131+ return s .toXContent (builder , ToXContent .EMPTY_PARAMS ).toString ();
132+ } catch (final IOException ex ) {
133+ throw new UncheckedIOException (ex );
134+ }
135+ }).collect (Collectors .joining ("\r \n " , "" , "\r \n " ))));
136+ } finally {
137+ response .release ();
138+ }
139+ }
140+ }
141+ }
142+
143+ public void testConnectionsGettingClosedForStreamingRequests () throws InterruptedException {
144+ final String responseString = randomAlphaOfLength (4 * 1024 );
145+ final String url = "/stream/" ;
146+
147+ final ToXContent [] chunks = newChunks (responseString );
148+ final HttpServerTransport .Dispatcher dispatcher = createStreamingDispatcher (url , responseString );
149+
150+ try (
151+ ReactorNetty4HttpServerTransport transport = new ReactorNetty4HttpServerTransport (
152+ Settings .EMPTY ,
153+ networkService ,
154+ bigArrays ,
155+ threadPool ,
156+ xContentRegistry (),
157+ dispatcher ,
158+ clusterSettings ,
159+ new SharedGroupFactory (Settings .EMPTY ),
160+ NoopTracer .INSTANCE
161+ );
162+ ReactorHttpClient client = ReactorHttpClient .create (false )
163+ ) {
164+ transport .start ();
165+ final TransportAddress remoteAddress = randomFrom (transport .boundAddress ().boundAddresses ());
166+ HttpRequest request = new DefaultHttpRequest (HttpVersion .HTTP_1_1 , HttpMethod .GET , url );
167+ long numRequests = randomLongBetween (5L , 15L );
168+ for (int i = 0 ; i < numRequests ; i ++) {
169+ logger .info ("Sending request {}/{}" , i + 1 , numRequests );
170+ final FullHttpResponse response = client .stream (remoteAddress .address (), request , Arrays .stream (chunks ));
171+ try {
172+ assertThat (response .status (), equalTo (HttpResponseStatus .OK ));
173+ } finally {
174+ response .release ();
175+ }
176+ }
177+ assertThat (transport .stats ().getServerOpen (), equalTo (0L ));
178+ assertThat (transport .stats ().getTotalOpen (), equalTo (numRequests ));
179+ }
180+ }
181+
182+ private HttpServerTransport .Dispatcher createStreamingDispatcher (String url , String responseString ) {
183+ return new HttpServerTransport .Dispatcher () {
105184 @ Override
106185 public Optional <RestHandler > dispatchHandler (String uri , String rawPath , Method method , Map <String , String > params ) {
107186 return Optional .of (new RestHandler () {
@@ -161,42 +240,6 @@ public void dispatchBadRequest(final RestChannel channel, final ThreadContext th
161240 }
162241
163242 };
164-
165- try (
166- ReactorNetty4HttpServerTransport transport = new ReactorNetty4HttpServerTransport (
167- Settings .EMPTY ,
168- networkService ,
169- bigArrays ,
170- threadPool ,
171- xContentRegistry (),
172- dispatcher ,
173- clusterSettings ,
174- new SharedGroupFactory (Settings .EMPTY ),
175- NoopTracer .INSTANCE
176- )
177- ) {
178- transport .start ();
179- final TransportAddress remoteAddress = randomFrom (transport .boundAddress ().boundAddresses ());
180-
181- try (ReactorHttpClient client = ReactorHttpClient .create (false )) {
182- HttpRequest request = new DefaultHttpRequest (HttpVersion .HTTP_1_1 , HttpMethod .GET , url );
183- final FullHttpResponse response = client .stream (remoteAddress .address (), request , Arrays .stream (chunks ));
184- try {
185- assertThat (response .status (), equalTo (HttpResponseStatus .OK ));
186- byte [] bytes = new byte [response .content ().readableBytes ()];
187- response .content ().readBytes (bytes );
188- assertThat (new String (bytes , StandardCharsets .UTF_8 ), equalTo (Arrays .stream (newChunks (responseString )).map (s -> {
189- try (XContentBuilder builder = XContentType .JSON .contentBuilder ()) {
190- return s .toXContent (builder , ToXContent .EMPTY_PARAMS ).toString ();
191- } catch (final IOException ex ) {
192- throw new UncheckedIOException (ex );
193- }
194- }).collect (Collectors .joining ("\r \n " , "" , "\r \n " ))));
195- } finally {
196- response .release ();
197- }
198- }
199- }
200243 }
201244
202245 private static ToXContent [] newChunks (final String responseString ) {
0 commit comments