3737import io .netty .channel .ChannelFuture ;
3838import io .netty .channel .ChannelHandlerContext ;
3939import io .netty .channel .ChannelPipeline ;
40+ import io .netty .channel .ChannelPromise ;
4041import io .netty .channel .DefaultFileRegion ;
4142import io .netty .handler .codec .http .DefaultFullHttpResponse ;
4243import io .netty .handler .codec .http .DefaultHttpHeaders ;
@@ -131,12 +132,20 @@ public void send(final InputStream stream) throws Exception {
131132 } else {
132133 DefaultHttpResponse rsp = new DefaultHttpResponse (HttpVersion .HTTP_1_1 , status );
133134
134- if (!headers .contains (HttpHeaderNames .CONTENT_LENGTH )) {
135+ boolean lenSet = headers .contains (HttpHeaderNames .CONTENT_LENGTH );
136+ final boolean keepAlive ;
137+ final ChannelPromise promise ;
138+ if (!lenSet ) {
135139 headers .set (HttpHeaderNames .TRANSFER_ENCODING , HttpHeaderValues .CHUNKED );
140+ keepAlive = false ;
141+ promise = ctx .newPromise ();
142+ } else if (this .keepAlive ) {
143+ headers .set (HttpHeaderNames .CONNECTION , HttpHeaderValues .KEEP_ALIVE );
144+ keepAlive = this .keepAlive ;
145+ promise = ctx .voidPromise ();
136146 } else {
137- if (keepAlive ) {
138- headers .set (HttpHeaderNames .CONNECTION , HttpHeaderValues .KEEP_ALIVE );
139- }
147+ keepAlive = false ;
148+ promise = ctx .newPromise ();
140149 }
141150
142151 // dump headers
@@ -155,7 +164,10 @@ public void send(final InputStream stream) throws Exception {
155164 ctx .write (buffer );
156165 // send tail
157166 ctx .write (new ChunkedStream (stream , bufferSize ));
158- keepAlive (ctx .writeAndFlush (LastHttpContent .EMPTY_LAST_CONTENT ));
167+ ChannelFuture future = ctx .writeAndFlush (LastHttpContent .EMPTY_LAST_CONTENT , promise );
168+ if (!keepAlive ) {
169+ future .addListener (CLOSE );
170+ }
159171 });
160172 }
161173
@@ -171,10 +183,8 @@ public void send(final FileChannel channel) throws Exception {
171183 public void send (final FileChannel channel , final long offset , final long count )
172184 throws Exception {
173185 DefaultHttpResponse rsp = new DefaultHttpResponse (HttpVersion .HTTP_1_1 , status );
174- if (!headers .contains (HttpHeaderNames .CONTENT_LENGTH )) {
175- headers .remove (HttpHeaderNames .TRANSFER_ENCODING );
176- headers .set (HttpHeaderNames .CONTENT_LENGTH , count );
177- }
186+ headers .remove (HttpHeaderNames .TRANSFER_ENCODING );
187+ headers .set (HttpHeaderNames .CONTENT_LENGTH , count );
178188
179189 if (keepAlive ) {
180190 headers .set (HttpHeaderNames .CONNECTION , HttpHeaderValues .KEEP_ALIVE );
@@ -198,17 +208,25 @@ public void send(final FileChannel channel, final long offset, final long count)
198208
199209 ctx .channel ().eventLoop ().execute (() -> {
200210 // send headers
201- ctx .write (rsp );
211+ ctx .write (rsp , ctx . voidPromise () );
202212 // chunked file
203- keepAlive (ctx .writeAndFlush (chunkedInput ));
213+ if (keepAlive ) {
214+ ctx .writeAndFlush (chunkedInput , ctx .voidPromise ());
215+ } else {
216+ ctx .writeAndFlush (chunkedInput ).addListener (CLOSE );
217+ }
204218 });
205219 } else {
206220 ctx .channel ().eventLoop ().execute (() -> {
207221 // send headers
208- ctx .write (rsp );
222+ ctx .write (rsp , ctx . voidPromise () );
209223 // file region
210- ctx .write (new DefaultFileRegion (channel , offset , count ));
211- keepAlive (ctx .writeAndFlush (LastHttpContent .EMPTY_LAST_CONTENT ));
224+ ctx .write (new DefaultFileRegion (channel , offset , count ), ctx .voidPromise ());
225+ if (keepAlive ) {
226+ ctx .writeAndFlush (LastHttpContent .EMPTY_LAST_CONTENT , ctx .voidPromise ());
227+ } else {
228+ ctx .writeAndFlush (LastHttpContent .EMPTY_LAST_CONTENT ).addListener (CLOSE );
229+ }
212230 });
213231 }
214232
@@ -219,39 +237,33 @@ public void send(final FileChannel channel, final long offset, final long count)
219237 private void send (final ByteBuf buffer ) throws Exception {
220238 DefaultFullHttpResponse rsp = new DefaultFullHttpResponse (HttpVersion .HTTP_1_1 , status , buffer );
221239
222- if (!headers .contains (HttpHeaderNames .CONTENT_LENGTH )) {
223- headers .remove (HttpHeaderNames .TRANSFER_ENCODING )
224- .set (HttpHeaderNames .CONTENT_LENGTH , buffer .readableBytes ());
225- }
240+ headers .remove (HttpHeaderNames .TRANSFER_ENCODING )
241+ .set (HttpHeaderNames .CONTENT_LENGTH , buffer .readableBytes ());
226242
243+ ChannelPromise promise ;
227244 if (keepAlive ) {
245+ promise = ctx .voidPromise ();
228246 headers .set (HttpHeaderNames .CONNECTION , HttpHeaderValues .KEEP_ALIVE );
247+ } else {
248+ promise = ctx .newPromise ();
229249 }
230250
231251 // dump headers
232252 rsp .headers ().set (headers );
233253
234254 Attribute <Boolean > async = ctx .channel ().attr (NettyRequest .ASYNC );
235- boolean isAsync = async != null && async .get () == Boolean .TRUE ;
236- if ( isAsync ) {
237- // we need flush, from async
238- keepAlive ( ctx .writeAndFlush (rsp ) );
255+ boolean flush = async != null && async .get () == Boolean .TRUE ;
256+ final ChannelFuture future ;
257+ if ( flush ) {
258+ future = ctx .writeAndFlush (rsp , promise );
239259 } else {
240- keepAlive ( ctx .write (rsp ) );
260+ future = ctx .write (rsp , promise );
241261 }
242-
243- committed = true ;
244- }
245-
246- private void keepAlive (final ChannelFuture future ) {
247- if (headers .contains (HttpHeaderNames .CONTENT_LENGTH )) {
248- if (!keepAlive ) {
249- future .addListener (CLOSE );
250- }
251- } else {
252- // content len is not set, just close the connection regardless keep alive or not.
262+ if (!keepAlive ) {
253263 future .addListener (CLOSE );
254264 }
265+
266+ committed = true ;
255267 }
256268
257269 @ Override
@@ -282,11 +294,16 @@ public void end() {
282294 }
283295 if (!committed ) {
284296 DefaultHttpResponse rsp = new DefaultFullHttpResponse (HttpVersion .HTTP_1_1 , status );
297+ headers .set (HttpHeaderNames .CONTENT_LENGTH , 0 );
285298 // dump headers
286299 rsp .headers ().set (headers );
287- keepAlive (ctx .write (rsp ));
300+ if (keepAlive ) {
301+ ctx .write (rsp , ctx .voidPromise ());
302+ } else {
303+ ctx .write (rsp ).addListener (CLOSE );
304+ }
305+ committed = true ;
288306 }
289- committed = true ;
290307 ctx = null ;
291308 }
292309 }
0 commit comments