@Override public int hashCode() { int result = 1; result = HASH_CODE_PRIME * result + status.hashCode(); result = HASH_CODE_PRIME * result + super.hashCode(); return result; }
private void sendError(ChannelHandlerContext ctx, HttpResponseStatus status) { HttpResponse response = new DefaultHttpResponse(HTTP_1_1, status); response.setHeader(CONTENT_TYPE, "text/plain; charset=UTF-8"); response.setContent( ChannelBuffers.copiedBuffer("Failure: " + status.toString() + "\r\n", CharsetUtil.UTF_8)); // Close the connection as soon as the error message is sent. ctx.getChannel().write(response).addListener(ChannelFutureListener.CLOSE); }
private static void sendError(ChannelHandlerContext ctx, HttpResponseStatus status) { FullHttpResponse response = new DefaultFullHttpResponse( HttpVersion.HTTP_1_1, status, Unpooled.copiedBuffer("Failure: " + status.toString() + "\r\n", CharsetUtil.UTF_8)); response.headers().set(HttpHeaderConstants.CONTENT_TYPE, "text/plain; charset=UTF-8"); // Close the connection as soon as the error message is sent. ctx.write(response).addListener(ChannelFutureListener.CLOSE); }
@Override public void failover(FullHttpRequest request, FullHttpResponse response) { Response dumpedResponse = failoverResponse(request); response.setProtocolVersion(HttpVersion.valueOf(dumpedResponse.getVersion())); response.setStatus(HttpResponseStatus.valueOf(dumpedResponse.getStatusCode())); for (Map.Entry<String, String> entry : dumpedResponse.getHeaders().entrySet()) { response.headers().add(entry.getKey(), entry.getValue()); } response.content().writeBytes(dumpedResponse.getContent().getBytes()); }
private static void parseHeaders(@NotNull HttpResponse response, @NotNull ByteBuf buffer) { StringBuilder builder = new StringBuilder(); while (buffer.isReadable()) { builder.setLength(0); String key = null; boolean valueExpected = true; while (true) { int b = buffer.readByte(); if (b < 0 || b == '\n') { break; } if (b != '\r') { if (valueExpected && b == ':') { valueExpected = false; key = builder.toString(); builder.setLength(0); MessageDecoder.skipWhitespace(buffer); } else { builder.append((char) b); } } } if (builder.length() == 0) { // end of headers return; } // skip standard headers if (StringUtil.isEmpty(key) || StringUtilRt.startsWithIgnoreCase(key, "http") || StringUtilRt.startsWithIgnoreCase(key, "X-Accel-")) { continue; } String value = builder.toString(); if (key.equalsIgnoreCase("status")) { int index = value.indexOf(' '); if (index == -1) { LOG.warn("Cannot parse status: " + value); response.setStatus(HttpResponseStatus.OK); } else { response.setStatus( HttpResponseStatus.valueOf(Integer.parseInt(value.substring(0, index)))); } } else if (!(key.startsWith("http") || key.startsWith("HTTP"))) { response.headers().add(key, value); } } }
@Override protected void encode(ChannelHandlerContext ctx, HttpResponse response, List<Object> out) { DefaultFullHttpResponse defaultFullHttpResponse = new DefaultFullHttpResponse( HttpVersion.HTTP_1_1, HttpResponseStatus.valueOf( (response.getStatusCode() != null ? response.getStatusCode() : 200)), getBody(response)); setHeaders(response, defaultFullHttpResponse); setCookies(response, defaultFullHttpResponse); out.add(defaultFullHttpResponse); }
public void serveStatic( RenderStatic renderStatic, ChannelHandlerContext ctx, Request request, Response response, HttpRequest nettyRequest, MessageEvent e) { Logger.trace("serveStatic: begin"); HttpResponse nettyResponse = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.valueOf(response.status)); if (exposePlayServer) { nettyResponse.setHeader(SERVER, signature); } try { VirtualFile file = Play.getVirtualFile(renderStatic.file); if (file != null && file.exists() && file.isDirectory()) { file = file.child("index.html"); if (file != null) { renderStatic.file = file.relativePath(); } } if ((file == null || !file.exists())) { serve404( new NotFound("The file " + renderStatic.file + " does not exist"), ctx, request, nettyRequest); } else { boolean raw = false; for (PlayPlugin plugin : Play.plugins) { if (plugin.serveStatic(file, Request.current(), Response.current())) { raw = true; break; } } if (raw) { copyResponse(ctx, request, response, nettyRequest); } else { final File localFile = file.getRealFile(); final boolean keepAlive = isKeepAlive(nettyRequest); nettyResponse = addEtag(nettyRequest, nettyResponse, localFile); if (nettyResponse.getStatus().equals(HttpResponseStatus.NOT_MODIFIED)) { Channel ch = e.getChannel(); // Write the initial line and the header. ChannelFuture writeFuture = ch.write(nettyResponse); if (!keepAlive) { // Write the content. writeFuture.addListener(ChannelFutureListener.CLOSE); } } else { final RandomAccessFile raf = new RandomAccessFile(localFile, "r"); try { long fileLength = raf.length(); Logger.trace("keep alive " + keepAlive); Logger.trace( "content type " + (MimeTypes.getContentType(localFile.getName(), "text/plain"))); if (keepAlive && !nettyResponse.getStatus().equals(HttpResponseStatus.NOT_MODIFIED)) { // Add 'Content-Length' header only for a keep-alive connection. Logger.trace("file length " + fileLength); setContentLength(nettyResponse, fileLength); } nettyResponse.setHeader( CONTENT_TYPE, (MimeTypes.getContentType(localFile.getName(), "text/plain"))); Channel ch = e.getChannel(); // Write the initial line and the header. ChannelFuture writeFuture = ch.write(nettyResponse); // Write the content. if (!nettyRequest.getMethod().equals(HttpMethod.HEAD)) { writeFuture = ch.write(new ChunkedFile(raf, 0, fileLength, 8192)); } else { raf.close(); } if (!keepAlive) { // Close the connection when the whole content is written out. writeFuture.addListener(ChannelFutureListener.CLOSE); } } catch (Throwable exx) { try { raf.close(); } catch (Throwable ex) { /* Left empty */ } try { ctx.getChannel().close(); } catch (Throwable ex) { /* Left empty */ } } } } } } catch (Throwable ez) { Logger.error(ez, "serveStatic for request %s", request.method + " " + request.url); try { HttpResponse errorResponse = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR); ChannelBuffer buf = ChannelBuffers.copiedBuffer("Internal Error (check logs)".getBytes("utf-8")); errorResponse.setContent(buf); ChannelFuture future = ctx.getChannel().write(errorResponse); future.addListener(ChannelFutureListener.CLOSE); } catch (Exception ex) { Logger.error(ez, "serveStatic for request %s", request.method + " " + request.url); } } Logger.trace("serveStatic: end"); }
public void copyResponse( ChannelHandlerContext ctx, Request request, Response response, HttpRequest nettyRequest) throws Exception { Logger.trace("copyResponse: begin"); // response.out.flush(); // Decide whether to close the connection or not. HttpResponse nettyResponse = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.valueOf(response.status)); if (exposePlayServer) { nettyResponse.setHeader(SERVER, signature); } if (response.contentType != null) { nettyResponse.setHeader( CONTENT_TYPE, response.contentType + (response.contentType.startsWith("text/") && !response.contentType.contains("charset") ? "; charset=utf-8" : "")); } else { nettyResponse.setHeader(CONTENT_TYPE, "text/plain; charset=utf-8"); } addToResponse(response, nettyResponse); final Object obj = response.direct; File file = null; ChunkedInput stream = null; InputStream is = null; if (obj instanceof File) { file = (File) obj; } else if (obj instanceof InputStream) { is = (InputStream) obj; } else if (obj instanceof ChunkedInput) { stream = (ChunkedInput) obj; } final boolean keepAlive = isKeepAlive(nettyRequest); if (file != null && file.isFile()) { try { nettyResponse = addEtag(nettyRequest, nettyResponse, file); if (nettyResponse.getStatus().equals(HttpResponseStatus.NOT_MODIFIED)) { Channel ch = ctx.getChannel(); // Write the initial line and the header. ChannelFuture writeFuture = ch.write(nettyResponse); if (!keepAlive) { // Close the connection when the whole content is written out. writeFuture.addListener(ChannelFutureListener.CLOSE); } } else { nettyResponse.setHeader( CONTENT_TYPE, MimeTypes.getContentType(file.getName(), "text/plain")); final RandomAccessFile raf = new RandomAccessFile(file, "r"); try { long fileLength = raf.length(); if (keepAlive) { // Add 'Content-Length' header only for a keep-alive connection. Logger.trace("file length is [" + fileLength + "]"); setContentLength(nettyResponse, fileLength); } Channel ch = ctx.getChannel(); // Write the initial line and the header. ChannelFuture writeFuture = ch.write(nettyResponse); // Write the content. // If it is not a HEAD if (!nettyRequest.getMethod().equals(HttpMethod.HEAD)) { writeFuture = ch.write(new ChunkedFile(raf, 0, fileLength, 8192)); } else { raf.close(); } if (!keepAlive) { // Close the connection when the whole content is written out. writeFuture.addListener(ChannelFutureListener.CLOSE); } } catch (Throwable exx) { try { raf.close(); } catch (Throwable ex) { /* Left empty */ } try { ctx.getChannel().close(); } catch (Throwable ex) { /* Left empty */ } } } } catch (Exception e) { throw e; } } else if (is != null) { ChannelFuture writeFuture = ctx.getChannel().write(nettyResponse); if (!nettyRequest.getMethod().equals(HttpMethod.HEAD) && !nettyResponse.getStatus().equals(HttpResponseStatus.NOT_MODIFIED)) { writeFuture = ctx.getChannel().write(new ChunkedStream(is)); } else { is.close(); } if (!keepAlive) { writeFuture.addListener(ChannelFutureListener.CLOSE); } } else if (stream != null) { ChannelFuture writeFuture = ctx.getChannel().write(nettyResponse); if (!nettyRequest.getMethod().equals(HttpMethod.HEAD) && !nettyResponse.getStatus().equals(HttpResponseStatus.NOT_MODIFIED)) { writeFuture = ctx.getChannel().write(stream); } else { stream.close(); } if (!keepAlive) { writeFuture.addListener(ChannelFutureListener.CLOSE); } } else { writeResponse(ctx, response, nettyResponse, nettyRequest); } Logger.trace("copyResponse: end"); }
@Override public final boolean trySend(HttpResponse message) { try { final HttpRequestWrapper nettyRequest = (HttpRequestWrapper) message.getRequest(); final FullHttpRequest req = nettyRequest.req; final ChannelHandlerContext ctx = nettyRequest.ctx; final HttpResponseStatus status = HttpResponseStatus.valueOf(message.getStatus()); if (message.getStatus() >= 400 && message.getStatus() < 600) { sendHttpResponse( ctx, req, new DefaultFullHttpResponse(req.getProtocolVersion(), status), false); close(); return true; } if (message.getRedirectPath() != null) { sendHttpRedirect(ctx, req, message.getRedirectPath()); close(); return true; } FullHttpResponse res; if (message.getStringBody() != null) res = new DefaultFullHttpResponse( req.getProtocolVersion(), status, Unpooled.wrappedBuffer(message.getStringBody().getBytes())); else if (message.getByteBufferBody() != null) res = new DefaultFullHttpResponse( req.getProtocolVersion(), status, Unpooled.wrappedBuffer(message.getByteBufferBody())); else res = new DefaultFullHttpResponse(req.getProtocolVersion(), status); if (message.getCookies() != null) { final ServerCookieEncoder enc = ServerCookieEncoder.STRICT; for (final Cookie c : message.getCookies()) HttpHeaders.setHeader(res, COOKIE, enc.encode(getNettyCookie(c))); } if (message.getHeaders() != null) { for (final Map.Entry<String, String> h : message.getHeaders().entries()) HttpHeaders.setHeader(res, h.getKey(), h.getValue()); } if (message.getContentType() != null) { String ct = message.getContentType(); if (message.getCharacterEncoding() != null) ct = ct + "; charset=" + message.getCharacterEncoding().name(); HttpHeaders.setHeader(res, CONTENT_TYPE, ct); } final boolean sseStarted = message.shouldStartActor(); if (trackSession(sseStarted)) { final String sessionId = UUID.randomUUID().toString(); res.headers() .add(SET_COOKIE, ServerCookieEncoder.STRICT.encode(SESSION_COOKIE_KEY, sessionId)); startSession(sessionId, actorContext); } if (!sseStarted) { final String stringBody = message.getStringBody(); long contentLength = 0L; if (stringBody != null) contentLength = stringBody.getBytes().length; else { final ByteBuffer byteBufferBody = message.getByteBufferBody(); if (byteBufferBody != null) contentLength = byteBufferBody.remaining(); } res.headers().add(CONTENT_LENGTH, contentLength); } final HttpStreamActorAdapter httpStreamActorAdapter; if (sseStarted) // This will copy the request content, which must still be referenceable, doing before the // request handler // unallocates it (unfortunately it is explicitly reference-counted in Netty) httpStreamActorAdapter = new HttpStreamActorAdapter(ctx, req); else httpStreamActorAdapter = null; sendHttpResponse(ctx, req, res, false); if (sseStarted) { if (httpResponseEncoderName != null) { ctx.pipeline().remove(httpResponseEncoderName); } else { final ChannelPipeline pl = ctx.pipeline(); final List<String> handlerKeysToBeRemoved = new ArrayList<>(); for (final Map.Entry<String, ChannelHandler> e : pl) { if (e.getValue() instanceof HttpResponseEncoder) handlerKeysToBeRemoved.add(e.getKey()); } for (final String k : handlerKeysToBeRemoved) pl.remove(k); } try { message.getFrom().send(new HttpStreamOpened(httpStreamActorAdapter.ref(), message)); } catch (SuspendExecution e) { throw new AssertionError(e); } } return true; } finally { if (actor != null) actor.unwatch(); } }