List of usage examples for io.netty.handler.codec.http LastHttpContent EMPTY_LAST_CONTENT
LastHttpContent EMPTY_LAST_CONTENT
To view the source code for io.netty.handler.codec.http LastHttpContent EMPTY_LAST_CONTENT.
Click Source Link
From source file:bean.lee.demo.netty.learn.http.file.HttpStaticFileServerHandler.java
License:Apache License
@Override public void messageReceived(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception { // ????/*ww w.ja v a 2s . c o m*/ if (!request.getDecoderResult().isSuccess()) { sendError(ctx, BAD_REQUEST); return; } // ?get if (request.getMethod() != GET) { sendError(ctx, METHOD_NOT_ALLOWED); return; } // uri?? final String uri = request.getUri(); final String path = sanitizeUri(uri); if (path == null) { sendError(ctx, FORBIDDEN); return; } // ?? File file = new File(path); if (file.isHidden() || !file.exists()) { sendError(ctx, NOT_FOUND); return; } //? if (file.isDirectory()) { if (uri.endsWith("/")) { sendListing(ctx, file); } else { sendRedirect(ctx, uri + '/'); } return; } //? if (!file.isFile()) { sendError(ctx, FORBIDDEN); return; } // Cache Validation String ifModifiedSince = request.headers().get(IF_MODIFIED_SINCE); if (ifModifiedSince != null && !ifModifiedSince.isEmpty()) { SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US); Date ifModifiedSinceDate = dateFormatter.parse(ifModifiedSince); // Only compare up to the second because the datetime format we send // to the client // does not have milliseconds long ifModifiedSinceDateSeconds = ifModifiedSinceDate.getTime() / 1000; long fileLastModifiedSeconds = file.lastModified() / 1000; if (ifModifiedSinceDateSeconds == fileLastModifiedSeconds) { sendNotModified(ctx); return; } } RandomAccessFile raf; try { raf = new RandomAccessFile(file, "r"); } catch (FileNotFoundException fnfe) { sendError(ctx, NOT_FOUND); return; } long fileLength = raf.length(); HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK); setContentLength(response, fileLength); setContentTypeHeader(response, file); setDateAndCacheHeaders(response, file); if (isKeepAlive(request)) { response.headers().set(CONNECTION, HttpHeaders.Values.KEEP_ALIVE); } // Write the initial line and the header. ctx.write(response); // Write the content. ChannelFuture sendFileFuture; if (useSendFile) { sendFileFuture = ctx.write(new DefaultFileRegion(raf.getChannel(), 0, fileLength), ctx.newProgressivePromise()); } else { sendFileFuture = ctx.write(new ChunkedFile(raf, 0, fileLength, 8192), ctx.newProgressivePromise()); } sendFileFuture.addListener(new ChannelProgressiveFutureListener() { @Override public void operationProgressed(ChannelProgressiveFuture future, long progress, long total) { if (total < 0) { // total unknown System.err.println("Transfer progress: " + progress); } else { System.err.println("Transfer progress: " + progress + " / " + total); } } @Override public void operationComplete(ChannelProgressiveFuture future) throws Exception { System.err.println("Transfer complete."); } }); // Write the end marker ChannelFuture lastContentFuture = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT); // Decide whether to close the connection or not. if (!isKeepAlive(request)) { // Close the connection when the whole content is written out. lastContentFuture.addListener(ChannelFutureListener.CLOSE); } }
From source file:books.netty.protocol.http.fileServer.HttpFileServerHandler.java
License:Apache License
@Override public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception { if (!request.getDecoderResult().isSuccess()) { sendError(ctx, BAD_REQUEST);//from w w w . j a v a2s . c o m return; } if (request.getMethod() != GET) { sendError(ctx, METHOD_NOT_ALLOWED); return; } final String uri = request.getUri(); final String path = sanitizeUri(uri); if (path == null) { sendError(ctx, FORBIDDEN); return; } File file = new File(path); if (file.isHidden() || !file.exists()) { sendError(ctx, NOT_FOUND); return; } if (file.isDirectory()) { if (uri.endsWith("/")) { sendListing(ctx, file); } else { sendRedirect(ctx, uri + '/'); } return; } if (!file.isFile()) { sendError(ctx, FORBIDDEN); return; } RandomAccessFile randomAccessFile = null; try { randomAccessFile = new RandomAccessFile(file, "r");// ?? } catch (FileNotFoundException fnfe) { sendError(ctx, NOT_FOUND); return; } long fileLength = randomAccessFile.length(); HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK); setContentLength(response, fileLength); setContentTypeHeader(response, file); if (isKeepAlive(request)) { response.headers().set(CONNECTION, HttpHeaders.Values.KEEP_ALIVE); } ctx.write(response); ChannelFuture sendFileFuture; sendFileFuture = ctx.write(new ChunkedFile(randomAccessFile, 0, fileLength, 8192), ctx.newProgressivePromise()); sendFileFuture.addListener(new ChannelProgressiveFutureListener() { @Override public void operationProgressed(ChannelProgressiveFuture future, long progress, long total) { if (total < 0) { // total unknown System.err.println("Transfer progress: " + progress); } else { System.err.println("Transfer progress: " + progress + " / " + total); } } @Override public void operationComplete(ChannelProgressiveFuture future) { System.out.println("Transfer complete."); } }); ChannelFuture lastContentFuture = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT); if (!isKeepAlive(request)) { lastContentFuture.addListener(ChannelFutureListener.CLOSE); } }
From source file:cn.yesway.demo.book.protocol.http.fileServer.HttpFileServerHandler.java
License:Apache License
@Override public void messageReceived(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception { if (!request.getDecoderResult().isSuccess()) { sendError(ctx, BAD_REQUEST);//www . j av a2 s . com return; } if (request.getMethod() != GET) { sendError(ctx, METHOD_NOT_ALLOWED); return; } final String uri = request.getUri(); final String path = sanitizeUri(uri); if (path == null) { sendError(ctx, FORBIDDEN); return; } File file = new File(path); if (file.isHidden() || !file.exists()) { sendError(ctx, NOT_FOUND); return; } if (file.isDirectory()) { if (uri.endsWith("/")) { sendListing(ctx, file); } else { sendRedirect(ctx, uri + '/'); } return; } if (!file.isFile()) { sendError(ctx, FORBIDDEN); return; } RandomAccessFile randomAccessFile = null; try { randomAccessFile = new RandomAccessFile(file, "r");// ?? } catch (FileNotFoundException fnfe) { sendError(ctx, NOT_FOUND); return; } long fileLength = randomAccessFile.length(); HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK); setContentLength(response, fileLength); setContentTypeHeader(response, file); if (isKeepAlive(request)) { response.headers().set(CONNECTION, HttpHeaders.Values.KEEP_ALIVE); } ctx.write(response); ChannelFuture sendFileFuture; sendFileFuture = ctx.write(new ChunkedFile(randomAccessFile, 0, fileLength, 8192), ctx.newProgressivePromise()); sendFileFuture.addListener(new ChannelProgressiveFutureListener() { @Override public void operationProgressed(ChannelProgressiveFuture future, long progress, long total) { if (total < 0) { // total unknown System.err.println("Transfer progress: " + progress); } else { System.err.println("Transfer progress: " + progress + " / " + total); } } @Override public void operationComplete(ChannelProgressiveFuture future) throws Exception { System.out.println("Transfer complete."); } }); ChannelFuture lastContentFuture = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT); if (!isKeepAlive(request)) { lastContentFuture.addListener(ChannelFutureListener.CLOSE); } }
From source file:com.addthis.hydra.query.tracker.DetailedStatusHandler.java
License:Apache License
private void onSuccess(QueryEntryInfo queryEntryInfo) { try {// ww w . j a va 2 s .c om JSONObject entryJSON = CodecJSON.encodeJSON(queryEntryInfo); writer.write(entryJSON.toString()); ByteBuf textResponse = ByteBufUtil.encodeString(ctx.alloc(), CharBuffer.wrap(writer.getBuilder()), CharsetUtil.UTF_8); HttpContent content = new DefaultHttpContent(textResponse); response.headers().set(HttpHeaders.Names.CONTENT_LENGTH, textResponse.readableBytes()); if (HttpHeaders.isKeepAlive(request)) { response.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.KEEP_ALIVE); } ctx.write(response); ctx.write(content); ChannelFuture lastContentFuture = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT); if (!HttpHeaders.isKeepAlive(request)) { lastContentFuture.addListener(ChannelFutureListener.CLOSE); } } catch (Throwable t) { onFailure(t); } }
From source file:com.addthis.hydra.query.web.DataChannelOutputToNettyBridge.java
License:Apache License
@Override public void sendComplete() { // TODO: keep alive logic log.trace("Writing sendComplete to pipeline {}", ctx.pipeline()); ctx.write(SEND_COMPLETE);/* w ww.j a v a 2 s . c om*/ // no need to make the frame reader wait on the async flush to finish overallQueryPromise.trySuccess(); ChannelFuture lastContentFuture = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT, ctx.channel().newPromise()); lastContentFuture.addListener(ChannelFutureListener.CLOSE); }
From source file:com.addthis.hydra.query.web.DetailedStatusHandler.java
License:Apache License
private void onSuccess(QueryEntryInfo queryEntryInfo) throws Exception { JSONObject entryJSON = CodecJSON.encodeJSON(queryEntryInfo); writer.write(entryJSON.toString());/*from www .j a v a 2s .co m*/ ByteBuf textResponse = ByteBufUtil.encodeString(ctx.alloc(), CharBuffer.wrap(writer.getBuilder()), CharsetUtil.UTF_8); HttpContent content = new DefaultHttpContent(textResponse); response.headers().set(HttpHeaders.Names.CONTENT_LENGTH, textResponse.readableBytes()); if (HttpHeaders.isKeepAlive(request)) { response.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.KEEP_ALIVE); } ctx.write(response); ctx.write(content); ChannelFuture lastContentFuture = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT); if (!HttpHeaders.isKeepAlive(request)) { lastContentFuture.addListener(ChannelFutureListener.CLOSE); } }
From source file:com.addthis.hydra.query.web.GoogleDriveAuthentication.java
License:Apache License
/** * Send an HTML formatted error message. *//*w ww. j a va 2 s.c o m*/ private static void sendErrorMessage(ChannelHandlerContext ctx, String message) throws IOException { HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); response.headers().set(CONTENT_TYPE, "text/html; charset=utf-8"); StringBuilderWriter writer = new StringBuilderWriter(50); writer.append("<html><head><title>Hydra Query Master</title></head><body>"); writer.append("<h3>"); writer.append(message); writer.append("</h3></body></html>"); ByteBuf textResponse = ByteBufUtil.encodeString(ctx.alloc(), CharBuffer.wrap(writer.getBuilder()), CharsetUtil.UTF_8); HttpContent content = new DefaultHttpContent(textResponse); response.headers().set(HttpHeaders.Names.CONTENT_LENGTH, textResponse.readableBytes()); ctx.write(response); ctx.write(content); ChannelFuture lastContentFuture = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT); lastContentFuture.addListener(ChannelFutureListener.CLOSE); }
From source file:com.addthis.hydra.query.web.GoogleDriveAuthentication.java
License:Apache License
/** * Obtain a Google authorization token. This token is worthless by itself. It * is an intermediate step to obtain an access token. We need to do these two * steps because...reasons./*from w ww . ja v a 2 s . c om*/ */ static void gdriveAuthorization(KVPairs kv, ChannelHandlerContext ctx) throws Exception { if (gdriveClientId == null && gdriveClientSecret == null) { sendErrorMessage(ctx, "The system properties \"qmaster.export.gdrive.clientId\"" + " and \"qmaster.export.gdrive.clientSecret\" are both null."); return; } else if (gdriveClientId == null) { sendErrorMessage(ctx, "The system property \"qmaster.export.gdrive.clientId\"" + " is null."); return; } else if (gdriveClientSecret == null) { sendErrorMessage(ctx, "The system property \"qmaster.export.gdrive.clientSecret\"" + " is null."); return; } else if (!gdriveEnabled) { sendErrorMessage(ctx, "The system property \"qmaster.export.gdrive.enable\"" + " is false."); return; } QueryStringEncoder encoder = new QueryStringEncoder(""); Iterator<KVPair> iterator = kv.iterator(); while (iterator.hasNext()) { KVPair pair = iterator.next(); encoder.addParam(pair.getKey(), pair.getValue()); } String state = encoder.toString().substring(1); URI uri = new URIBuilder().setScheme("https").setHost("accounts.google.com").setPath("/o/oauth2/auth") .setParameter("scope", "https://www.googleapis.com/auth/drive.file").setParameter("state", state) .setParameter("redirect_uri", "http://" + generateTargetHostName() + ":2222/query/google/submit") .setParameter("response_type", "code").setParameter("client_id", gdriveClientId).build(); FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.FOUND); response.headers().set(HttpHeaders.Names.LOCATION, uri); ctx.write(response); ChannelFuture lastContentFuture = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT); log.trace("response pending"); log.trace("Setting close listener"); lastContentFuture.addListener(ChannelFutureListener.CLOSE); }
From source file:com.addthis.hydra.query.web.HttpQueryHandler.java
License:Apache License
private void fastHandle(ChannelHandlerContext ctx, FullHttpRequest request, String target, KVPairs kv) throws Exception { StringBuilderWriter writer = new StringBuilderWriter(50); HttpResponse response = HttpUtils.startResponse(writer); response.headers().add("Access-Control-Allow-Origin", "*"); switch (target) { case "/metrics": fakeMetricsServlet.writeMetrics(writer, kv); break;// w ww.j a va2s. c o m case "/query/list": writer.write("[\n"); for (QueryEntryInfo stat : tracker.getRunning()) { writer.write(CodecJSON.encodeString(stat).concat(",\n")); } writer.write("]"); break; case "/completed/list": writer.write("[\n"); for (QueryEntryInfo stat : tracker.getCompleted()) { writer.write(CodecJSON.encodeString(stat).concat(",\n")); } writer.write("]"); break; case "/v2/host/list": case "/host/list": String queryStatusUuid = kv.getValue("uuid"); QueryEntry queryEntry = tracker.getQueryEntry(queryStatusUuid); if (queryEntry != null) { DetailedStatusHandler hostDetailsHandler = new DetailedStatusHandler(writer, response, ctx, request, queryEntry); hostDetailsHandler.handle(); return; } else { QueryEntryInfo queryEntryInfo = tracker.getCompletedQueryInfo(queryStatusUuid); if (queryEntryInfo != null) { JSONObject entryJSON = CodecJSON.encodeJSON(queryEntryInfo); writer.write(entryJSON.toString()); } else { throw new RuntimeException("could not find query"); } break; } case "/query/cancel": if (tracker.cancelRunning(kv.getValue("uuid"))) { writer.write("canceled " + kv.getValue("uuid")); } else { writer.write("canceled failed for " + kv.getValue("uuid")); response.setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR); } break; case "/query/encode": { Query q = new Query(null, kv.getValue("query", kv.getValue("path", "")), null); JSONArray path = CodecJSON.encodeJSON(q).getJSONArray("path"); writer.write(path.toString()); break; } case "/query/decode": { String qo = "{path:" + kv.getValue("query", kv.getValue("path", "")) + "}"; Query q = CodecJSON.decodeString(new Query(), qo); writer.write(q.getPaths()[0]); break; } case "/v2/queries/finished.list": { JSONArray runningEntries = new JSONArray(); for (QueryEntryInfo entryInfo : tracker.getCompleted()) { JSONObject entryJSON = CodecJSON.encodeJSON(entryInfo); //TODO: replace this with some high level summary entryJSON.put("hostInfoSet", ""); runningEntries.put(entryJSON); } writer.write(runningEntries.toString()); break; } case "/v2/queries/running.list": { JSONArray runningEntries = new JSONArray(); for (QueryEntryInfo entryInfo : tracker.getRunning()) { JSONObject entryJSON = CodecJSON.encodeJSON(entryInfo); //TODO: replace this with some high level summary entryJSON.put("hostInfoSet", ""); runningEntries.put(entryJSON); } writer.write(runningEntries.toString()); break; } case "/v2/queries/workers": { JSONObject jsonObject = new JSONObject(); for (WorkerData workerData : meshQueryMaster.worky().values()) { jsonObject.put(workerData.hostName, workerData.queryLeases.availablePermits()); } writer.write(jsonObject.toString()); break; } case "/v2/queries/list": JSONArray queries = new JSONArray(); for (QueryEntryInfo entryInfo : tracker.getCompleted()) { JSONObject entryJSON = CodecJSON.encodeJSON(entryInfo); entryJSON.put("state", 0); queries.put(entryJSON); } for (QueryEntryInfo entryInfo : tracker.getRunning()) { JSONObject entryJSON = CodecJSON.encodeJSON(entryInfo); entryJSON.put("state", 3); queries.put(entryJSON); } writer.write(queries.toString()); break; case "/v2/job/list": { StringWriter swriter = new StringWriter(); final JsonGenerator json = QueryServer.factory.createJsonGenerator(swriter); json.writeStartArray(); for (IJob job : meshQueryMaster.keepy().getJobs()) { if (job.getQueryConfig() != null && job.getQueryConfig().getCanQuery()) { List<JobTask> tasks = job.getCopyOfTasks(); String uuid = job.getId(); json.writeStartObject(); json.writeStringField("id", uuid); json.writeStringField("description", Optional.fromNullable(job.getDescription()).or("")); json.writeNumberField("state", job.getState().ordinal()); json.writeStringField("creator", job.getCreator()); json.writeNumberField("submitTime", Optional.fromNullable(job.getSubmitTime()).or(-1L)); json.writeNumberField("startTime", Optional.fromNullable(job.getStartTime()).or(-1L)); json.writeNumberField("endTime", Optional.fromNullable(job.getStartTime()).or(-1L)); json.writeNumberField("replicas", Optional.fromNullable(job.getReplicas()).or(0)); json.writeNumberField("backups", Optional.fromNullable(job.getBackups()).or(0)); json.writeNumberField("nodes", tasks.size()); json.writeEndObject(); } } json.writeEndArray(); json.close(); writer.write(swriter.toString()); break; } case "/v2/settings/git.properties": { StringWriter swriter = new StringWriter(); final JsonGenerator json = QueryServer.factory.createJsonGenerator(swriter); Properties gitProperties = new Properties(); json.writeStartObject(); try { InputStream in = queryServer.getClass().getResourceAsStream("/git.properties"); gitProperties.load(in); in.close(); json.writeStringField("commitIdAbbrev", gitProperties.getProperty("git.commit.id.abbrev")); json.writeStringField("commitUserEmail", gitProperties.getProperty("git.commit.user.email")); json.writeStringField("commitMessageFull", gitProperties.getProperty("git.commit.message.full")); json.writeStringField("commitId", gitProperties.getProperty("git.commit.id")); json.writeStringField("commitUserName", gitProperties.getProperty("git.commit.user.name")); json.writeStringField("buildUserName", gitProperties.getProperty("git.build.user.name")); json.writeStringField("commitIdDescribe", gitProperties.getProperty("git.commit.id.describe")); json.writeStringField("buildUserEmail", gitProperties.getProperty("git.build.user.email")); json.writeStringField("branch", gitProperties.getProperty("git.branch")); json.writeStringField("commitTime", gitProperties.getProperty("git.commit.time")); json.writeStringField("buildTime", gitProperties.getProperty("git.build.time")); } catch (Exception ex) { log.warn("Error loading git.properties, possibly jar was not compiled with maven."); } json.writeEndObject(); json.close(); writer.write(swriter.toString()); break; } default: // forward to static file server ctx.pipeline().addLast(staticFileHandler); request.retain(); ctx.fireChannelRead(request); return; // don't do text response clean up } log.trace("response being sent {}", writer); ByteBuf textResponse = ByteBufUtil.encodeString(ctx.alloc(), CharBuffer.wrap(writer.getBuilder()), CharsetUtil.UTF_8); HttpContent content = new DefaultHttpContent(textResponse); response.headers().set(HttpHeaders.Names.CONTENT_LENGTH, textResponse.readableBytes()); if (HttpHeaders.isKeepAlive(request)) { response.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.KEEP_ALIVE); } ctx.write(response); ctx.write(content); ChannelFuture lastContentFuture = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT); log.trace("response pending"); if (!HttpHeaders.isKeepAlive(request)) { log.trace("Setting close listener"); lastContentFuture.addListener(ChannelFutureListener.CLOSE); } }
From source file:com.addthis.hydra.query.web.HttpStaticFileHandler.java
License:Apache License
@Override public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception { if (!request.getDecoderResult().isSuccess()) { sendError(ctx, BAD_REQUEST);/*from w ww . j a v a 2s . c o m*/ return; } // since we are using send file, we must remove the compression unit or it will donk out ChannelHandler compressor = ctx.pipeline().get("compressor"); if (compressor != null) { ctx.pipeline().remove("compressor"); } if (request.getMethod() != GET) { sendError(ctx, METHOD_NOT_ALLOWED); return; } QueryStringDecoder urlDecoder = new QueryStringDecoder(request.getUri()); String target = urlDecoder.path(); final String path = sanitizeUri(target); if (path == null) { sendError(ctx, FORBIDDEN); return; } Path file = Paths.get(webDir + path); log.trace("trying to serve static file {}", file); if (Files.isHidden(file) || Files.notExists(file)) { sendError(ctx, NOT_FOUND); return; } if (!Files.isRegularFile(file)) { sendError(ctx, FORBIDDEN); return; } log.trace("cache validation occuring for {}", file); // Cache Validation String ifModifiedSince = request.headers().get(IF_MODIFIED_SINCE); if (ifModifiedSince != null && !ifModifiedSince.isEmpty()) { SimpleDateFormat dateFormatter = new SimpleDateFormat(HttpUtils.HTTP_DATE_FORMAT, Locale.US); Date ifModifiedSinceDate = dateFormatter.parse(ifModifiedSince); // Only compare up to the second because the datetime format we send to the client // does not have milliseconds long ifModifiedSinceDateSeconds = ifModifiedSinceDate.getTime() / 1000; long fileLastModifiedSeconds = Files.getLastModifiedTime(file).toMillis() / 1000; if (ifModifiedSinceDateSeconds == fileLastModifiedSeconds) { sendNotModified(ctx); return; } } log.trace("sending {}", file); FileChannel fileChannel; try { fileChannel = FileChannel.open(file, StandardOpenOption.READ); } catch (IOException fnfe) { sendError(ctx, NOT_FOUND); return; } long fileLength = fileChannel.size(); HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK); setContentLength(response, fileLength); setContentTypeHeader(response, file); try { setDateAndCacheHeaders(response, file); } catch (IOException ioex) { fileChannel.close(); sendError(ctx, NOT_FOUND); return; } if (isKeepAlive(request)) { response.headers().set(CONNECTION, HttpHeaders.Values.KEEP_ALIVE); } // Write the initial line and the header. ctx.write(response); // Write the content. ctx.write(new DefaultFileRegion(fileChannel, 0, fileLength)); // Write the end marker ChannelFuture lastContentFuture = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT); // Decide whether to close the connection or not. if (!isKeepAlive(request)) { // Close the connection when the whole content is written out. lastContentFuture.addListener(ChannelFutureListener.CLOSE); } else { ctx.pipeline().remove(this); if (compressor != null) { ctx.pipeline().addBefore("query", "compressor", compressor); } } }