Example #1
0
  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");
  }
Example #2
0
 @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;
   }
 }
Example #3
0
 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);
   }
 }
Example #4
0
 @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);
   }
 }
Example #5
0
  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());
          }
        }
      }
    }
  }
Example #6
0
 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 ?)");
   }
 }
Example #7
0
 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);
   }
 }
Example #8
0
    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);
      }
    }
Example #9
0
  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");
  }
Example #10
0
  // 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");
  }
Example #11
0
  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");
  }