public static void serve404( NotFound e, ChannelHandlerContext ctx, Request request, HttpRequest nettyRequest) { Logger.trace("serve404: begin"); HttpResponse nettyResponse = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.NOT_FOUND); nettyResponse.setHeader(SERVER, signature); nettyResponse.setHeader(CONTENT_TYPE, "text/html"); Map<String, Object> binding = getBindingForErrors(e, false); String format = Request.current().format; if (format == null) { format = "txt"; } nettyResponse.setHeader( CONTENT_TYPE, (MimeTypes.getContentType("404." + format, "text/plain"))); String errorHtml = TemplateLoader.load("errors/404." + format).render(binding); try { ChannelBuffer buf = ChannelBuffers.copiedBuffer(errorHtml.getBytes("utf-8")); nettyResponse.setContent(buf); ChannelFuture writeFuture = ctx.getChannel().write(nettyResponse); writeFuture.addListener(ChannelFutureListener.CLOSE); } catch (UnsupportedEncodingException fex) { Logger.error(fex, "(utf-8 ?)"); } Logger.trace("serve404: end"); }
@Test public void contentTypeShouldReturnResponseCharsetWhenAvailable() throws Exception { String oldEncoding = Response.current().encoding; try { Response.current().encoding = "my-response-encoding"; assertEquals("text/xml; charset=my-response-encoding", MimeTypes.getContentType("test.xml")); } finally { Response.current().encoding = oldEncoding; } }
public static void upload(File[] files) throws FileNotFoundException { Files f = null; for (File file : files) { f = new Files(); f.name = file.getName(); f.path = ""; f.image = new Blob(); f.image.set(new FileInputStream(file), MimeTypes.getContentType(file.getName())); f.save(); renderText(f.id); } }
@Test public void contentTypeShouldReturnDefaultCharsetInAbsenceOfResponse() throws Exception { Response originalResponse = Response.current(); try { Response.current.set(null); assertEquals( "text/xml; charset=" + play.Play.defaultWebEncoding, MimeTypes.getContentType("test.xml")); } finally { Response.current.set(originalResponse); } }
public void serveStatic( HttpServletResponse servletResponse, HttpServletRequest servletRequest, RenderStatic renderStatic) throws IOException { VirtualFile file = Play.getVirtualFile(renderStatic.file); if (file == null || file.isDirectory() || !file.exists()) { serve404( servletRequest, servletResponse, new NotFound("The file " + renderStatic.file + " does not exist")); } else { servletResponse.setContentType(MimeTypes.getContentType(file.getName())); boolean raw = false; for (PlayPlugin plugin : Play.plugins) { if (plugin.serveStatic(file, Request.current(), Response.current())) { raw = true; break; } } if (raw) { copyResponse(Request.current(), Response.current(), servletRequest, servletResponse); } else { if (Play.mode == Play.Mode.DEV) { servletResponse.setHeader("Cache-Control", "no-cache"); servletResponse.setHeader("Content-Length", String.valueOf(file.length())); if (!servletRequest.getMethod().equals("HEAD")) { copyStream(servletResponse, file.inputstream()); } else { copyStream(servletResponse, new ByteArrayInputStream(new byte[0])); } } else { long last = file.lastModified(); String etag = "\"" + last + "-" + file.hashCode() + "\""; if (!isModified(etag, last, servletRequest)) { servletResponse.setHeader("Etag", etag); servletResponse.setStatus(304); } else { servletResponse.setHeader( "Last-Modified", Utils.getHttpDateFormatter().format(new Date(last))); servletResponse.setHeader( "Cache-Control", "max-age=" + Play.configuration.getProperty("http.cacheControl", "3600")); servletResponse.setHeader("Etag", etag); copyStream(servletResponse, file.inputstream()); } } } } }
public void serve404( HttpServletRequest servletRequest, HttpServletResponse servletResponse, NotFound e) { Logger.warn( "404 -> %s %s (%s)", servletRequest.getMethod(), servletRequest.getRequestURI(), e.getMessage()); servletResponse.setStatus(404); servletResponse.setContentType("text/html"); Map<String, Object> binding = new HashMap<String, Object>(); binding.put("result", e); binding.put("session", Scope.Session.current()); binding.put("request", Http.Request.current()); binding.put("flash", Scope.Flash.current()); binding.put("params", Scope.Params.current()); binding.put("play", new Play()); try { binding.put("errors", Validation.errors()); } catch (Exception ex) { // } String format = Request.current().format; servletResponse.setStatus(404); // Do we have an ajax request? If we have then we want to display some text even if it is html // that is requested if ("XMLHttpRequest".equals(servletRequest.getHeader("X-Requested-With")) && (format == null || format.equals("html"))) { format = "txt"; } if (format == null) { format = "txt"; } servletResponse.setContentType(MimeTypes.getContentType("404." + format, "text/plain")); String errorHtml = TemplateLoader.load("errors/404." + format).render(binding); try { servletResponse.getOutputStream().write(errorHtml.getBytes(Response.current().encoding)); } catch (Exception fex) { Logger.error(fex, "(encoding ?)"); } }
public void serve500(Exception e, HttpServletRequest request, HttpServletResponse response) { try { Map<String, Object> binding = new HashMap<String, Object>(); if (!(e instanceof PlayException)) { e = new play.exceptions.UnexpectedException(e); } // Flush some cookies try { Map<String, Http.Cookie> cookies = Response.current().cookies; for (Http.Cookie cookie : cookies.values()) { if (cookie.sendOnError) { Cookie c = new Cookie(cookie.name, cookie.value); c.setSecure(cookie.secure); c.setPath(cookie.path); if (cookie.domain != null) { c.setDomain(cookie.domain); } response.addCookie(c); } } } catch (Exception exx) { // humm ? } binding.put("exception", e); binding.put("session", Scope.Session.current()); binding.put("request", Http.Request.current()); binding.put("flash", Scope.Flash.current()); binding.put("params", Scope.Params.current()); binding.put("play", new Play()); try { binding.put("errors", Validation.errors()); } catch (Exception ex) { // } response.setStatus(500); String format = "html"; if (Request.current() != null) { format = Request.current().format; } // Do we have an ajax request? If we have then we want to display some text even if it is html // that is requested if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With")) && (format == null || format.equals("html"))) { format = "txt"; } if (format == null) { format = "txt"; } response.setContentType(MimeTypes.getContentType("500." + format, "text/plain")); try { String errorHtml = TemplateLoader.load("errors/500." + format).render(binding); response.getOutputStream().write(errorHtml.getBytes(Response.current().encoding)); Logger.error(e, "Internal Server Error (500)"); } catch (Throwable ex) { Logger.error(e, "Internal Server Error (500)"); Logger.error(ex, "Error during the 500 response generation"); throw ex; } } catch (Throwable exxx) { if (exxx instanceof RuntimeException) { throw (RuntimeException) exxx; } throw new RuntimeException(exxx); } }
private void checkFileBody(BoundRequestBuilder builder) { setResolvedContentType(null); if (this.fileParams != null) { // could be optimized, we know the size of this array. for (int i = 0; i < this.fileParams.length; i++) { builder.addBodyPart( new FilePart( this.fileParams[i].paramName, this.fileParams[i].file, MimeTypes.getMimeType(this.fileParams[i].file.getName()), encoding)); } if (this.parameters != null) { try { // AHC only supports ascii chars in keys in multipart for (String key : this.parameters.keySet()) { Object value = this.parameters.get(key); if (value instanceof Collection<?> || value.getClass().isArray()) { Collection<?> values = value.getClass().isArray() ? Arrays.asList((Object[]) value) : (Collection<?>) value; for (Object v : values) { Part part = new ByteArrayPart( key, null, v.toString().getBytes(encoding), "text/plain", encoding); builder.addBodyPart(part); } } else { Part part = new ByteArrayPart( key, null, value.toString().getBytes(encoding), "text/plain", encoding); builder.addBodyPart(part); } } } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } // Don't have to set content-type: AHC will automatically choose multipart return; } if (this.parameters != null && !this.parameters.isEmpty()) { boolean isPostPut = "POST".equals(this.type) || ("PUT".equals(this.type)); if (isPostPut) { // Since AHC is hard-coded to encode to use UTF-8, we must build // the content ourself.. StringBuilder sb = new StringBuilder(); for (String key : this.parameters.keySet()) { Object value = this.parameters.get(key); if (value == null) continue; if (value instanceof Collection<?> || value.getClass().isArray()) { Collection<?> values = value.getClass().isArray() ? Arrays.asList((Object[]) value) : (Collection<?>) value; for (Object v : values) { if (sb.length() > 0) { sb.append('&'); } sb.append(encode(key)); sb.append('='); sb.append(encode(v.toString())); } } else { // Since AHC is hard-coded to encode using UTF-8, we must build // the content ourself.. if (sb.length() > 0) { sb.append('&'); } sb.append(encode(key)); sb.append('='); sb.append(encode(value.toString())); } } try { byte[] bodyBytes = sb.toString().getBytes(this.encoding); InputStream bodyInStream = new ByteArrayInputStream(bodyBytes); builder.setBody(bodyInStream); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } setResolvedContentType("application/x-www-form-urlencoded; charset=" + encoding); } else { for (String key : this.parameters.keySet()) { Object value = this.parameters.get(key); if (value == null) continue; if (value instanceof Collection<?> || value.getClass().isArray()) { Collection<?> values = value.getClass().isArray() ? Arrays.asList((Object[]) value) : (Collection<?>) value; for (Object v : values) { // must encode it since AHC uses raw urls builder.addQueryParameter(encode(key), encode(v.toString())); } } else { // must encode it since AHC uses raw urls builder.addQueryParameter(encode(key), encode(value.toString())); } } setResolvedContentType("text/html; charset=" + encoding); } } if (this.body != null) { if (this.parameters != null && !this.parameters.isEmpty()) { throw new RuntimeException( "POST or PUT method with parameters AND body are not supported."); } if (this.body instanceof InputStream) { builder.setBody((InputStream) this.body); } else { try { byte[] bodyBytes = this.body.toString().getBytes(this.encoding); InputStream bodyInStream = new ByteArrayInputStream(bodyBytes); builder.setBody(bodyInStream); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } setResolvedContentType("text/html; charset=" + encoding); } if (this.mimeType != null) { // User has specified mimeType this.headers.put("Content-Type", this.mimeType); } }
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"); }
// TODO: add request and response as parameter public static void serve500(Exception e, ChannelHandlerContext ctx, HttpRequest nettyRequest) { Logger.trace("serve500: begin"); HttpResponse nettyResponse = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR); if (exposePlayServer) { nettyResponse.setHeader(SERVER, signature); } Request request = Request.current(); Response response = Response.current(); try { if (!(e instanceof PlayException)) { e = new play.exceptions.UnexpectedException(e); } // Flush some cookies try { Map<String, Http.Cookie> cookies = response.cookies; for (Http.Cookie cookie : cookies.values()) { CookieEncoder encoder = new CookieEncoder(true); Cookie c = new DefaultCookie(cookie.name, cookie.value); c.setSecure(cookie.secure); c.setPath(cookie.path); if (cookie.domain != null) { c.setDomain(cookie.domain); } if (cookie.maxAge != null) { c.setMaxAge(cookie.maxAge); } c.setHttpOnly(cookie.httpOnly); encoder.addCookie(c); nettyResponse.addHeader(SET_COOKIE, encoder.encode()); } } catch (Exception exx) { Logger.error(e, "Trying to flush cookies"); // humm ? } Map<String, Object> binding = getBindingForErrors(e, true); String format = request.format; if (format == null) { format = "txt"; } nettyResponse.setHeader( "Content-Type", (MimeTypes.getContentType("500." + format, "text/plain"))); try { String errorHtml = TemplateLoader.load("errors/500." + format).render(binding); ChannelBuffer buf = ChannelBuffers.copiedBuffer(errorHtml.getBytes("utf-8")); nettyResponse.setContent(buf); ChannelFuture writeFuture = ctx.getChannel().write(nettyResponse); writeFuture.addListener(ChannelFutureListener.CLOSE); Logger.error( e, "Internal Server Error (500) for request %s", request.method + " " + request.url); } catch (Throwable ex) { Logger.error( e, "Internal Server Error (500) for request %s", request.method + " " + request.url); Logger.error(ex, "Error during the 500 response generation"); try { ChannelBuffer buf = ChannelBuffers.copiedBuffer("Internal Error (check logs)".getBytes("utf-8")); nettyResponse.setContent(buf); ChannelFuture writeFuture = ctx.getChannel().write(nettyResponse); writeFuture.addListener(ChannelFutureListener.CLOSE); } catch (UnsupportedEncodingException fex) { Logger.error(fex, "(utf-8 ?)"); } } } catch (Throwable exxx) { try { ChannelBuffer buf = ChannelBuffers.copiedBuffer("Internal Error (check logs)".getBytes("utf-8")); nettyResponse.setContent(buf); ChannelFuture writeFuture = ctx.getChannel().write(nettyResponse); writeFuture.addListener(ChannelFutureListener.CLOSE); } catch (Exception fex) { Logger.error(fex, "(utf-8 ?)"); } if (exxx instanceof RuntimeException) { throw (RuntimeException) exxx; } throw new RuntimeException(exxx); } Logger.trace("serve500: 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"); }