private void sendHttpResponse(ActorRef sender, HttpResponseStatus status, String response) {

    // headers
    Map<String, List<String>> headers = new HashMap<String, List<String>>();
    headers.put(HttpHeaders.Names.CONTENT_TYPE, Arrays.asList("text/plain"));

    // response
    if (StringUtils.isEmpty(response)) {
      response = status.getReasonPhrase();
    }

    sender.tell(
        new HttpResponse(status.getCode(), headers, response.getBytes(Charset.forName("UTF-8"))),
        getSelf());
  }
示例#2
0
  public static HttpResponse buildHttpServletResponse(HttpResponseExchange forwardResponse)
      throws IOException {

    if (null == forwardResponse) {
      return new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.REQUEST_TIMEOUT);
    }
    HttpResponse response =
        new DefaultHttpResponse(
            HttpVersion.HTTP_1_1, HttpResponseStatus.valueOf(forwardResponse.getResponseCode()));

    List<String[]> headers = forwardResponse.getHeaders();
    for (String[] header : headers) {
      if (header[0].equalsIgnoreCase(HttpHeaders.Names.SET_COOKIE)
          || header[0].equalsIgnoreCase(HttpHeaders.Names.SET_COOKIE2)) {
        List<SetCookieHeaderValue> cookies = SetCookieHeaderValue.parse(header[1]);
        for (SetCookieHeaderValue cookie : cookies) {
          response.addHeader(header[0], cookie.toString());
        }
      } else {
        response.addHeader(header[0], header[1]);
      }
    }
    byte[] content = forwardResponse.getBody();
    if (null != content) {
      ChannelBuffer bufer = ChannelBuffers.wrappedBuffer(content);
      response.setContent(bufer);
    }

    return response;
  }
  /**
   * Writes the specified TaskResult data to the channel output. Only the raw output data is written
   * and rest of the TaskResult fields are ignored
   *
   * @param ctx the ChannelHandlerContext
   * @param event the ChannelEvent
   * @throws Exception in case of any errors
   */
  private void writeCommandExecutionResponse(
      ChannelHandlerContext ctx, ChannelEvent event, HttpResponse response) throws Exception {
    // Don't write anything if the response is null
    if (response == null) {
      // write empty response
      event
          .getChannel()
          .write(new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.NO_CONTENT))
          .addListener(ChannelFutureListener.CLOSE);
      return;
    }
    org.jboss.netty.handler.codec.http.HttpResponse httpResponse =
        new DefaultHttpResponse(
            HttpVersion.HTTP_1_1,
            HttpResponseStatus.valueOf(response.getStatusLine().getStatusCode()));
    // write headers
    for (Header header : response.getAllHeaders()) {
      if (!RoutingHttpChannelHandler.REMOVE_HEADERS.contains(header.getName())) {
        httpResponse.setHeader(header.getName(), header.getValue());
      }
    }

    // write entity
    HttpEntity responseEntity = response.getEntity();
    byte[] responseData = EntityUtils.toByteArray(responseEntity);
    httpResponse.setContent(ChannelBuffers.copiedBuffer(responseData));
    // write response
    event.getChannel().write(httpResponse).addListener(ChannelFutureListener.CLOSE);
  }
示例#4
0
  @Override
  public void postCall(HttpRequest request, HttpResponseStatus status, HandlerInfo handlerInfo) {
    if (metricsCollectionService != null) {
      try {
        MetricsCollector collector = collectorCache.get(createContext(handlerInfo));
        String name;
        int code = status.getCode();
        if (code < 100) {
          name = "unknown";
        } else if (code < 200) {
          name = "information";
        } else if (code < 300) {
          name = "successful";
        } else if (code < 400) {
          name = "redirect";
        } else if (code < 500) {
          name = "client-error";
        } else if (code < 600) {
          name = "server-error";
        } else {
          name = "unknown";
        }

        // todo: report metrics broken down by status
        collector.increment("response." + name, 1 /*, "status:" + code*/);
      } catch (Throwable e) {
        LOG.error("Got exception while getting collector", e);
      }
    }
  }
  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);
  }
  @Override
  public AsyncIOWriter writeError(int errorCode, String message) throws IOException {
    if (!channel.isOpen()) {
      return this;
    }

    try {
      DefaultHttpResponse response =
          new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.valueOf(errorCode));
      channel.write(response).addListener(ChannelFutureListener.CLOSE);
    } catch (Throwable ex) {
      logger.debug("", ex);
    }
    return this;
  }
 private void writeHead() {
   if (!headWritten) {
     HttpResponseStatus status =
         statusMessage == null
             ? HttpResponseStatus.valueOf(statusCode)
             : new HttpResponseStatus(statusCode, statusMessage);
     response.setStatus(status);
     if (chunked) {
       response.setHeader(Names.TRANSFER_ENCODING, HttpHeaders.Values.CHUNKED);
     } else if (contentLength == 0) {
       response.setHeader(HttpHeaders.Names.CONTENT_LENGTH, "0");
     }
     writeFuture = conn.write(response);
     headWritten = true;
   }
 }
示例#8
0
 public static String httpMessage2String(HttpMessageExhange msg) {
   StringBuilder buffer = new StringBuilder();
   buffer.append("\r\n============================================\r\n");
   if (msg instanceof HttpResponseExchange) {
     int resCode = ((HttpResponseExchange) msg).responseCode;
     buffer.append(HttpResponseStatus.valueOf(resCode)).append("\r\n");
   } else {
     HttpRequestExchange req = (HttpRequestExchange) msg;
     buffer.append(req.method).append("  ").append(req.url).append("\r\n");
   }
   List<String[]> hs = msg.getHeaders();
   for (String[] header : hs) {
     buffer.append(header[0]).append(":").append(header[1]).append("\r\n");
   }
   buffer.append("============================================\r\n");
   return buffer.toString();
 }
  @Override
  public HttpResponse toNettyResponse(Message message, NettyHttpConfiguration configuration)
      throws Exception {
    LOG.trace("toNettyResponse: {}", message);

    // the message body may already be a Netty HTTP response
    if (message.getBody() instanceof HttpResponse) {
      return (HttpResponse) message.getBody();
    }

    // the response code is 200 for OK and 500 for failed
    boolean failed = message.getExchange().isFailed();
    int defaultCode = failed ? 500 : 200;

    int code = message.getHeader(Exchange.HTTP_RESPONSE_CODE, defaultCode, int.class);
    HttpResponse response =
        new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.valueOf(code));
    LOG.trace("HTTP Status Code: {}", code);

    TypeConverter tc = message.getExchange().getContext().getTypeConverter();

    // append headers
    // must use entrySet to ensure case of keys is preserved
    for (Map.Entry<String, Object> entry : message.getHeaders().entrySet()) {
      String key = entry.getKey();
      Object value = entry.getValue();
      // use an iterator as there can be multiple values. (must not use a delimiter)
      final Iterator<?> it = ObjectHelper.createIterator(value, null);
      while (it.hasNext()) {
        String headerValue = tc.convertTo(String.class, it.next());
        if (headerValue != null
            && headerFilterStrategy != null
            && !headerFilterStrategy.applyFilterToCamelHeaders(
                key, headerValue, message.getExchange())) {
          LOG.trace("HTTP-Header: {}={}", key, headerValue);
          response.headers().add(key, headerValue);
        }
      }
    }

    Object body = message.getBody();
    Exception cause = message.getExchange().getException();
    // support bodies as native Netty
    ChannelBuffer buffer;

    // if there was an exception then use that as body
    if (cause != null) {
      if (configuration.isTransferException()) {
        // we failed due an exception, and transfer it as java serialized object
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(cause);
        oos.flush();
        IOHelper.close(oos, bos);

        // the body should be the serialized java object of the exception
        body = ChannelBuffers.copiedBuffer(bos.toByteArray());
        // force content type to be serialized java object
        message.setHeader(
            Exchange.CONTENT_TYPE, NettyHttpConstants.CONTENT_TYPE_JAVA_SERIALIZED_OBJECT);
      } else {
        // we failed due an exception so print it as plain text
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        cause.printStackTrace(pw);

        // the body should then be the stacktrace
        body = ChannelBuffers.copiedBuffer(sw.toString().getBytes());
        // force content type to be text/plain as that is what the stacktrace is
        message.setHeader(Exchange.CONTENT_TYPE, "text/plain");
      }

      // and mark the exception as failure handled, as we handled it by returning it as the response
      ExchangeHelper.setFailureHandled(message.getExchange());
    }

    if (body instanceof ChannelBuffer) {
      buffer = (ChannelBuffer) body;
    } else {
      // try to convert to buffer first
      buffer = message.getBody(ChannelBuffer.class);
      if (buffer == null) {
        // fallback to byte array as last resort
        byte[] data = message.getBody(byte[].class);
        if (data != null) {
          buffer = ChannelBuffers.copiedBuffer(data);
        } else {
          // and if byte array fails then try String
          String str;
          if (body != null) {
            str = message.getMandatoryBody(String.class);
          } else {
            str = "";
          }
          buffer = ChannelBuffers.copiedBuffer(str.getBytes());
        }
      }
    }
    if (buffer != null) {
      response.setContent(buffer);
      // We just need to reset the readerIndex this time
      if (buffer.readerIndex() == buffer.writerIndex()) {
        buffer.setIndex(0, buffer.writerIndex());
      }
      // TODO How to enable the chunk transport
      int len = buffer.readableBytes();
      // set content-length
      response.headers().set(HttpHeaders.Names.CONTENT_LENGTH, len);
      LOG.trace("Content-Length: {}", len);
    }

    // set the content type in the response.
    String contentType = MessageHelper.getContentType(message);
    if (contentType != null) {
      // set content-type
      response.headers().set(HttpHeaders.Names.CONTENT_TYPE, contentType);
      LOG.trace("Content-Type: {}", contentType);
    }

    // configure connection to accordingly to keep alive configuration
    // favor using the header from the message
    String connection = message.getHeader(HttpHeaders.Names.CONNECTION, String.class);
    // Read the connection header from the exchange property
    if (connection == null) {
      connection = message.getExchange().getProperty(HttpHeaders.Names.CONNECTION, String.class);
    }
    if (connection == null) {
      // fallback and use the keep alive from the configuration
      if (configuration.isKeepAlive()) {
        connection = HttpHeaders.Values.KEEP_ALIVE;
      } else {
        connection = HttpHeaders.Values.CLOSE;
      }
    }
    response.headers().set(HttpHeaders.Names.CONNECTION, connection);
    // Just make sure we close the channel when the connection value is close
    if (connection.equalsIgnoreCase(HttpHeaders.Values.CLOSE)) {
      message.setHeader(NettyConstants.NETTY_CLOSE_CHANNEL_WHEN_COMPLETE, true);
    }
    LOG.trace("Connection: {}", connection);

    return response;
  }
示例#10
0
 @Override
 public NettyHttpResponse status(int status) {
   response.setStatus(HttpResponseStatus.valueOf(status));
   return this;
 }
 @Override
 public void setStatus(int sc, String msg) {
   response.setStatus(HttpResponseStatus.valueOf(sc));
 }
 private String getResponseCounterName(HttpResponseStatus responseStatus) {
   return responseStatus.getCode() + "-" + responseStatus.getReasonPhrase() + "-count";
 }
 @Override
 public void setStatus(int status) {
   this.nettyResponse.setStatus(HttpResponseStatus.valueOf(status));
 }
示例#14
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");
  }
示例#15
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");
  }