Beispiel #1
0
  public void sendError() {
    if (request == null
        || status == null
        || shortDescription == null
        || detailedDescription == null
        || version == null
        || status == null) throw new IllegalStateException();

    StringBuffer sb = new StringBuffer();
    sb.append("Error ").append(status.code()).append(": ").append(shortDescription);
    sb.append("\n\n");
    sb.append(detailedDescription);
    sb.append("\n\n");
    sb.append("Request:\n").append(request.getUri());
    sb.append("\n\n");
    sb.append("Request Submitted:\n").append(FdsnwsDate.toString(new Date()));
    sb.append("\n\n");
    sb.append("Service version:\n").append(version);
    String html = sb.toString();

    FullHttpResponse response =
        new DefaultFullHttpResponse(
            request.getProtocolVersion(),
            status,
            Unpooled.copiedBuffer(html, Charset.forName("UTF-8")));
    response.headers().set(HttpHeaders.Names.CONTENT_LENGTH, html.length());
    response.headers().set(HttpHeaders.Names.CONTENT_TYPE, "text/plain; charset=UTF-8");

    if (HttpHeaders.isKeepAlive(request)) {
      response.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.KEEP_ALIVE);
    }
    ctx.writeAndFlush(response);
  }
  @Override
  protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {

    FullHttpRequest req = (FullHttpRequest) msg;
    String upgrade = req.headers().get(HttpHeaders.Names.UPGRADE);
    if (HttpHeaders.Values.WEBSOCKET.equalsIgnoreCase(upgrade)) {
      WebSocketServerHandshakerFactory wsFactory =
          new WebSocketServerHandshakerFactory(req.getUri(), null, false);
      WebSocketServerHandshaker handshaker = wsFactory.newHandshaker(req);
      if (handshaker == null) {
        WebSocketServerHandshakerFactory.sendUnsupportedWebSocketVersionResponse(ctx.channel());
      } else {
        ChannelFuture future = handshaker.handshake(ctx.channel(), req);
        future.addListener(
            f -> {
              this.configurator.switchToWebSockets(ctx.pipeline());
            });
      }
    } else {
      ReferenceCountUtil.retain(msg);
      this.configurator.switchToPlainHttp(ctx.pipeline());
      ChannelHandlerContext agg = ctx.pipeline().context(HttpObjectAggregator.class);
      agg.fireChannelRead(msg);
    }
  }
Beispiel #3
0
 @Override
 public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
   FullHttpResponse res;
   FullHttpRequest req = (FullHttpRequest) msg;
   String url = req.getUri();
   if ("/".equals(req.getUri())) {
     url = "/index.html";
   }
   Path path = Paths.get(root + url);
   if (Files.isReadable(path)) {
     ByteBuf content = Unpooled.copiedBuffer(Files.readAllBytes(path));
     res = new DefaultFullHttpResponse(HTTP_1_1, OK, content);
     if (url.endsWith(".html")) res.headers().set(CONTENT_TYPE, "text/html; charset=UTF-8");
     HttpHeaders.setContentLength(res, content.readableBytes());
   } else {
     res = new DefaultFullHttpResponse(HTTP_1_1, NOT_FOUND);
   }
   sendHttpResponse(ctx, req, res);
 }
 @Override
 protected void decode(
     ChannelHandlerContext channelHandlerContext,
     FullHttpRequest fullHttpRequest,
     List<Object> objects)
     throws Exception {
   Request request = new Request();
   request.setHttpRequest(fullHttpRequest);
   request.setUri(fullHttpRequest.getUri());
   objects.add(request);
 }
  protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception {

    String uri = msg.getUri();

    Matcher matcher = processDefinitionIdPattern.matcher(uri);

    if (matcher.matches()) {
      String processDefinitionId = matcher.group(1);
      ChannelAttributes.setProcessDefinitionId(ctx.channel(), processDefinitionId);
    }
  }
  private void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest req) {
    // Handle a bad request.
    if (!req.getDecoderResult().isSuccess()) {
      sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, BAD_REQUEST));
      return;
    }

    // Allow only GET methods.
    if (req.getMethod() != GET) {
      sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, FORBIDDEN));
      return;
    }

    // Send the demo page and favicon.ico
    if ("/".equals(req.getUri())) {
      ByteBuf content = WebSocketServerIndexPage.getContent(getWebSocketLocation(req));
      FullHttpResponse res = new DefaultFullHttpResponse(HTTP_1_1, OK, content);

      res.headers().set(CONTENT_TYPE, "text/html; charset=UTF-8");
      HttpHeaders.setContentLength(res, content.readableBytes());

      sendHttpResponse(ctx, req, res);
      return;
    }
    if ("/favicon.ico".equals(req.getUri())) {
      FullHttpResponse res = new DefaultFullHttpResponse(HTTP_1_1, NOT_FOUND);
      sendHttpResponse(ctx, req, res);
      return;
    }

    // Handshake
    WebSocketServerHandshakerFactory wsFactory =
        new WebSocketServerHandshakerFactory(getWebSocketLocation(req), null, true);
    handshaker = wsFactory.newHandshaker(req);
    if (handshaker == null) {
      WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel());
    } else {
      handshaker.handshake(ctx.channel(), req);
    }
  }
  @Override
  public Object decode(FullHttpRequest request) {
    String uri = request.getUri();
    if (!uriPattern.matcher(uri).matches()) {
      throw new PumaEventRequestDecodeException("Illegal event ack request[%s].", request);
    }

    EventAckRequest eventAckRequest = new EventAckRequest();
    Map<String, List<String>> params = (new QueryStringDecoder(request.getUri())).parameters();

    eventAckRequest.setClientName(params.get("clientName").get(0));

    eventAckRequest.setToken(params.get("token").get(0));

    ClientAck clientAck = new ClientAck();
    clientAck.setServerId(Long.valueOf(params.get("serverId").get(0)));
    clientAck.setFilename(params.get("binlogFile").get(0));
    clientAck.setPosition(Long.valueOf(params.get("binlogPosition").get(0)));
    clientAck.setTimestamp(Long.valueOf(params.get("timestamp").get(0)));

    eventAckRequest.setClientAck(clientAck);

    return eventAckRequest;
  }
 @SuppressWarnings("unchecked")
 private Pair<ActorRef<? extends WebMessage>, Class<? extends ActorImpl<? extends WebMessage>>>
     autoCreateActor(FullHttpRequest req) {
   registerActorClasses();
   final String uri = req.getUri();
   for (final Class<?> c : actorClasses) {
     if (WebActorHandler.handlesWithHttp(uri, c) || WebActorHandler.handlesWithWebSocket(uri, c))
       return new Pair<
           ActorRef<? extends WebMessage>, Class<? extends ActorImpl<? extends WebMessage>>>(
           Actor.newActor(
                   new ActorSpec(
                       c, actorParams != null ? actorParams.get(c) : EMPTY_OBJECT_ARRAY))
               .spawn(),
           (Class<? extends ActorImpl<? extends WebMessage>>) c);
   }
   return null;
 }
  private void processHead(ChannelHandlerContext context, FullHttpRequest request) {
    HttpHeaders headers = request.headers();
    FullHttpResponse response = null;

    if (headers.contains(Names.CONTENT_LENGTH)) {

      try {
        File file = getRequestedFile(request.getUri());

        response =
            new DefaultFullHttpResponse(
                HTTP_1_1, request.getDecoderResult().isSuccess() ? OK : BAD_REQUEST);

        HttpHeaders.setContentLength(response, file.length());

      } catch (FileNotFoundException | URISyntaxException e) {
        response = getBadRequest(e.getMessage());
      }
    }

    context.writeAndFlush(response);
  }
  private void processGet(ChannelHandlerContext context, FullHttpRequest request) {
    try {
      File file = getRequestedFile(request.getUri());

      RandomAccessFile raf = new RandomAccessFile(file, "r");
      long fileLength = raf.length();

      HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
      HttpHeaders.setContentLength(response, fileLength);
      setContentTypeHeader(response, file);

      context.write(response);

      context.write(new DefaultFileRegion(raf.getChannel(), 0, fileLength));

      // Write the end marker.
      ChannelFuture future = context.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
      future.addListener(ChannelFutureListener.CLOSE);

    } catch (IOException | URISyntaxException e) {
      context.writeAndFlush(getBadRequest(e.getMessage()));
    }
  }
  protected void contentType(FullHttpRequest request, HttpResponse response, File resource) {
    String substr;
    String uri = request.getUri();
    int dot = uri.lastIndexOf(".");
    if (dot < 0) {
      substr = resource.toString();
      dot = substr.lastIndexOf(".");
    } else {
      substr = uri;
    }

    if (dot > 0) {
      String ext = substr.substring(dot + 1);
      int queryString = ext.indexOf("?");
      if (queryString > 0) {
        ext.substring(0, queryString);
      }
      String contentType = MimeType.get(ext, defaultContentType);
      response.headers().add(HttpHeaders.Names.CONTENT_TYPE, contentType);
    } else {
      response.headers().add(HttpHeaders.Names.CONTENT_TYPE, defaultContentType);
    }
  }
  public void channelRead0(final ChannelHandlerContext ctx, final FullHttpRequest nettyRequest)
      throws Exception {
    if (!nettyRequest.getDecoderResult().isSuccess()) {
      sendError(ctx, HttpResponseStatus.BAD_REQUEST);
      return;
    }

    final long startTime = addResponseTimeHeader ? System.nanoTime() : 0;
    final Request request =
        new DefaultRequest(
            new NettyHeadersBackedHeaders(nettyRequest.headers()),
            nettyRequest.getMethod().name(),
            nettyRequest.getUri(),
            nettyRequest.content());
    final Channel channel = ctx.channel();
    final DefaultMutableStatus responseStatus = new DefaultMutableStatus();
    final HttpHeaders nettyHeaders = new DefaultHttpHeaders(false);
    final MutableHeaders responseHeaders = new NettyHeadersBackedMutableHeaders(nettyHeaders);
    final MimeTypes mimeTypes = registry.get(MimeTypes.class);
    final DefaultEventController<RequestOutcome> requestOutcomeEventController =
        new DefaultEventController<>();
    final AtomicBoolean transmitted = new AtomicBoolean(false);

    final ResponseTransmitter responseTransmitter =
        new DefaultResponseTransmitter(
            transmitted,
            channel,
            nettyRequest,
            request,
            nettyHeaders,
            responseStatus,
            requestOutcomeEventController,
            startTime);
    final Action<Action<? super ResponseTransmitter>> responseTransmitterWrapper =
        Actions.wrap(responseTransmitter);

    final FileHttpTransmitter fileHttpTransmitter =
        new DefaultFileHttpTransmitter(
            nettyHeaders,
            mimeTypes,
            compressResponses,
            compressionMinSize,
            compressionMimeTypeWhiteList,
            compressionMimeTypeBlackList,
            responseTransmitterWrapper);
    StreamTransmitter streamTransmitter =
        new DefaultStreamTransmitter(nettyRequest, nettyHeaders, channel);

    final Response response =
        new DefaultResponse(
            responseStatus,
            responseHeaders,
            fileHttpTransmitter,
            streamTransmitter,
            ctx.alloc(),
            new Action<ByteBuf>() {
              @Override
              public void execute(final ByteBuf byteBuf) throws Exception {
                responseTransmitterWrapper.execute(
                    new Action<ResponseTransmitter>() {
                      @Override
                      public void execute(ResponseTransmitter responseTransmitter)
                          throws Exception {
                        nettyHeaders.set(HttpHeaders.Names.CONTENT_LENGTH, byteBuf.writerIndex());
                        responseTransmitter.transmit(new DefaultHttpContent(byteBuf));
                      }
                    });
              }
            });

    InetSocketAddress socketAddress = (InetSocketAddress) channel.localAddress();
    final BindAddress bindAddress = new InetSocketAddressBackedBindAddress(socketAddress);

    Action<Action<Object>> subscribeHandler =
        new Action<Action<Object>>() {
          @Override
          public void execute(Action<Object> thing) throws Exception {
            transmitted.set(true);
            channelSubscriptions.put(channel, thing);
            channel
                .closeFuture()
                .addListener(
                    new ChannelFutureListener() {
                      @Override
                      public void operationComplete(ChannelFuture future) throws Exception {
                        channelSubscriptions.remove(channel);
                      }
                    });
          }
        };

    final DirectChannelAccess directChannelAccess =
        new DefaultDirectChannelAccess(channel, subscribeHandler);

    final DefaultContext.RequestConstants requestConstants =
        new DefaultContext.RequestConstants(
            applicationConstants,
            bindAddress,
            request,
            response,
            directChannelAccess,
            requestOutcomeEventController.getRegistry());

    DefaultContext.start(
        execController.getControl(),
        requestConstants,
        registry,
        handlers,
        return404,
        new Action<Execution>() {
          @Override
          public void execute(Execution execution) throws Exception {
            if (!transmitted.get()) {
              Handler lastHandler = requestConstants.handler;
              StringBuilder description = new StringBuilder();
              description
                  .append("No response sent for ")
                  .append(request.getMethod().getName())
                  .append(" request to ")
                  .append(request.getUri())
                  .append(" (last handler: ");

              if (lastHandler instanceof DescribingHandler) {
                ((DescribingHandler) lastHandler).describeTo(description);
              } else {
                DescribingHandlers.describeTo(lastHandler, description);
              }

              description.append(")");
              String message = description.toString();
              LOGGER.warn(message);

              response.status(500);

              if (launchConfig.isDevelopment()) {
                response.send(message);
              } else {
                response.send();
              }
            }
          }
        });
  }
  @Override
  public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception {
    if (!request.getDecoderResult().isSuccess()) {
      sendError(ctx, BAD_REQUEST, request);
      return;
    }

    if (request.getMethod() != GET) {
      sendError(ctx, METHOD_NOT_ALLOWED, request);
      return;
    }

    File file = null;
    RandomAccessFile raf = null;
    boolean found = true;
    for (String p : paths) {
      String path = p + sanitizeUri(request.getUri());

      if (path == null) {
        path = "/index.html";
      }

      if (path.endsWith("/") || path.endsWith(File.separator)) {
        path += "index.html";
      }

      if (path.endsWith("/favicon.ico") || path.endsWith(File.separator)) {
        request.headers().add(SERVICED, "true");
        found = false;
        continue;
      }

      file = new File(path);
      if (file.isHidden() || !file.exists()) {
        found = false;
        continue;
      }

      //            if (file.isDirectory()) {
      //                if (uri.endsWith("/")) {
      //                    sendListing(ctx, file);
      //                } else {
      //                    sendRedirect(ctx, uri + '/');
      //                }
      //                return;
      //            }

      if (!file.isFile()) {
        found = false;
        continue;
      }

      try {
        raf = new RandomAccessFile(file, "r");
        found = true;
        break;
      } catch (FileNotFoundException ignore) {
        sendError(ctx, NOT_FOUND, request);
        return;
      }
    }

    if (!found) {
      sendError(ctx, NOT_FOUND, request);
      return;
    }
    request.headers().add(SERVICED, "true");

    // 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;
      }
    }

    long fileLength = raf.length();

    ctx.pipeline().addBefore(BridgeRuntime.class.getName(), "encoder", new HttpResponseEncoder());
    HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
    HttpHeaders.setContentLength(response, fileLength);
    contentType(request, response, file);
    setDateAndCacheHeaders(response, file);
    //        if (HttpHeaders.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;
    ChannelFuture lastContentFuture;
    if (ctx.pipeline().get(SslHandler.class) == null) {
      sendFileFuture =
          ctx.write(
              new DefaultFileRegion(raf.getChannel(), 0, fileLength), ctx.newProgressivePromise());
      // Write the end marker.
      lastContentFuture = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
    } else {
      sendFileFuture =
          ctx.writeAndFlush(
              new HttpChunkedInput(new ChunkedFile(raf, 0, fileLength, 8192)),
              ctx.newProgressivePromise());
      // HttpChunkedInput will write the end marker (LastHttpContent) for us.
      lastContentFuture = sendFileFuture;
    }

    sendFileFuture.addListener(
        new ChannelProgressiveFutureListener() {
          @Override
          public void operationProgressed(
              ChannelProgressiveFuture future, long progress, long total) {
            if (total < 0) { // total unknown
              logger.trace(future.channel() + " Transfer progress: " + progress);
            } else {
              logger.trace(future.channel() + " Transfer progress: " + progress + " / " + total);
            }
          }

          @Override
          public void operationComplete(ChannelProgressiveFuture future) {
            logger.trace(future.channel() + " Transfer complete.");
          }
        });

    // Close the connection when the whole content is written out.
    lastContentFuture.addListener(ChannelFutureListener.CLOSE);
  }
  public void channelRead0(final ChannelHandlerContext ctx, final FullHttpRequest nettyRequest)
      throws Exception {
    if (!nettyRequest.getDecoderResult().isSuccess()) {
      sendError(ctx, HttpResponseStatus.BAD_REQUEST);
      return;
    }

    final long startTime = System.nanoTime();

    final Request request =
        new DefaultRequest(
            new NettyHeadersBackedHeaders(nettyRequest.headers()),
            nettyRequest.getMethod().name(),
            nettyRequest.getUri(),
            nettyRequest.content());

    final Channel channel = ctx.channel();

    final DefaultMutableStatus responseStatus = new DefaultMutableStatus();
    final HttpHeaders httpHeaders = new DefaultHttpHeaders(false);
    final MutableHeaders responseHeaders = new NettyHeadersBackedMutableHeaders(httpHeaders);
    FileHttpTransmitter fileHttpTransmitter =
        new DefaultFileHttpTransmitter(
            nettyRequest,
            httpHeaders,
            channel,
            compressResponses,
            addResponseTimeHeader ? startTime : -1);

    final DefaultEventController<RequestOutcome> requestOutcomeEventController =
        new DefaultEventController<>();

    // We own the lifecycle
    nettyRequest.content().retain();

    final Response response =
        new DefaultResponse(
            responseStatus,
            responseHeaders,
            fileHttpTransmitter,
            ctx.alloc(),
            new Action<ByteBuf>() {
              @Override
              public void execute(final ByteBuf byteBuf) throws Exception {
                final HttpResponse nettyResponse =
                    new CustomHttpResponse(responseStatus.getResponseStatus(), httpHeaders);

                nettyRequest.content().release();
                responseHeaders.set(HttpHeaderConstants.CONTENT_LENGTH, byteBuf.writerIndex());
                boolean shouldClose = true;
                if (channel.isOpen()) {
                  if (isKeepAlive(nettyRequest)) {
                    responseHeaders.set(
                        HttpHeaderConstants.CONNECTION, HttpHeaderConstants.KEEP_ALIVE);
                    shouldClose = false;
                  }

                  long stopTime = System.nanoTime();
                  if (addResponseTimeHeader) {
                    responseHeaders.set(
                        "X-Response-Time", NumberUtil.toMillisDiffString(startTime, stopTime));
                  }

                  execController.getExecution().complete();

                  channel.writeAndFlush(nettyResponse);
                  channel.write(new DefaultHttpContent(byteBuf));
                  ChannelFuture future = channel.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);

                  if (requestOutcomeEventController.isHasListeners()) {
                    Headers headers = new DelegatingHeaders(responseHeaders);
                    Status status =
                        new DefaultStatus(responseStatus.getCode(), responseStatus.getMessage());
                    SentResponse sentResponse = new DefaultSentResponse(headers, status);
                    RequestOutcome requestOutcome =
                        new DefaultRequestOutcome(
                            request, sentResponse, System.currentTimeMillis());
                    requestOutcomeEventController.fire(requestOutcome);
                  }
                  if (shouldClose) {
                    future.addListener(ChannelFutureListener.CLOSE);
                  }
                }
              }
            });

    InetSocketAddress socketAddress = (InetSocketAddress) channel.localAddress();
    final BindAddress bindAddress = new InetSocketAddressBackedBindAddress(socketAddress);

    Action<Action<Object>> subscribeHandler =
        new Action<Action<Object>>() {
          @Override
          public void execute(Action<Object> thing) throws Exception {
            channelSubscriptions.put(channel, thing);
            channel
                .closeFuture()
                .addListener(
                    new ChannelFutureListener() {
                      @Override
                      public void operationComplete(ChannelFuture future) throws Exception {
                        channelSubscriptions.remove(channel);
                      }
                    });
          }
        };

    final DirectChannelAccess directChannelAccess =
        new DefaultDirectChannelAccess(channel, subscribeHandler);

    execController.start(
        new Action<Execution>() {
          @Override
          public void execute(Execution execution) throws Exception {
            DefaultContext.RequestConstants requestConstants =
                new DefaultContext.RequestConstants(
                    applicationConstants,
                    bindAddress,
                    request,
                    response,
                    directChannelAccess,
                    requestOutcomeEventController.getRegistry(),
                    execution);

            new DefaultContext(requestConstants, registry, handlers, 0, return404).next();
          }
        });
  }
  private void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest request) {
    // Handle a bad request.
    if (!request.getDecoderResult().isSuccess()) {
      sendHttpResponse(
          ctx, request, new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.BAD_REQUEST));
      return;
    }

    if (RouterHits.checkIfMappingExit(request)) {
      // Do Router Mapping First
      RouterHits.execute(ctx, request);
      return;
    }

    if ("/websocket".equals(request.getUri())) {
      // Handshake
      WebSocketServerHandshakerFactory wsFactory =
          new WebSocketServerHandshakerFactory(getWebSocketLocation(request), null, true);
      handshaker = wsFactory.newHandshaker(request);
      if (handshaker == null) {
        WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel());
      } else {
        handshaker.handshake(ctx.channel(), request);
        channels.add(ctx.channel());
      }
      return;
    }

    final String uri = request.getUri();
    // System.out.println("uri: " + uri);
    final String path = sanitizeUri("www", uri);
    // System.out.println("path: " + path);
    if (path == null) {
      sendHttpResponse(
          ctx, request, new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.FORBIDDEN));

      return;
    }

    File file = new File(path);
    if (file.isHidden() || !file.exists()) {
      sendHttpResponse(
          ctx, request, new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.NOT_FOUND));
      return;
    }

    if (file.isDirectory()) {
      if (uri.endsWith("/")) {

        File checkIndexFile = new File(file.getAbsolutePath() + File.separator + "index.html");

        System.out.println(checkIndexFile.exists());
        if (checkIndexFile.exists()) {
          file = checkIndexFile;
        } else {
          sendListing(ctx, file);
          return;
        }
      } else {
        sendRedirect(ctx, uri + '/');
      }
    }

    if (!file.isFile()) {
      sendHttpResponse(
          ctx, request, new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.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 = null;
      try {
        ifModifiedSinceDate = dateFormatter.parse(ifModifiedSince);
      } catch (ParseException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }

      // 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 ignore) {
      sendHttpResponse(
          ctx, request, new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.NOT_FOUND));
      return;
    }
    long fileLength = 0;
    try {
      fileLength = raf.length();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }

    HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
    HttpHeaders.setContentLength(response, fileLength);
    setContentTypeHeader(response, file);
    setDateAndCacheHeaders(response, file);
    if (HttpHeaders.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 = null;
    ChannelFuture lastContentFuture;
    if (ctx.pipeline().get(SslHandler.class) == null) {
      sendFileFuture =
          ctx.write(
              new DefaultFileRegion(raf.getChannel(), 0, fileLength), ctx.newProgressivePromise());
      // Write the end marker.
      lastContentFuture = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
    } else {
      try {
        sendFileFuture =
            ctx.writeAndFlush(
                new HttpChunkedInput(new ChunkedFile(raf, 0, fileLength, 8192)),
                ctx.newProgressivePromise());
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
      // HttpChunkedInput will write the end marker (LastHttpContent) for us.
      lastContentFuture = sendFileFuture;
    }

    sendFileFuture.addListener(
        new ChannelProgressiveFutureListener() {
          @Override
          public void operationProgressed(
              ChannelProgressiveFuture future, long progress, long total) {
            if (total < 0) { // total unknown
              System.err.println(future.channel() + " Transfer progress: " + progress);
            } else {
              System.err.println(
                  future.channel() + " Transfer progress: " + progress + " / " + total);
            }
          }

          @Override
          public void operationComplete(ChannelProgressiveFuture future) {
            System.err.println(future.channel() + " Transfer complete.");
          }
        });

    // Decide whether to close the connection or not.
    if (!HttpHeaders.isKeepAlive(request)) {
      // Close the connection when the whole content is written out.
      lastContentFuture.addListener(ChannelFutureListener.CLOSE);
    }

    //        // Send the demo page and favicon.ico
    //        if ("/".equals(req.getUri()) && req.getMethod() == GET) {
    //            ByteBuf content = WebSocketServerIndexPage.getContent(getWebSocketLocation(req));
    //            FullHttpResponse res = new DefaultFullHttpResponse(HTTP_1_1, OK, content);
    //
    //            res.headers().set(CONTENT_TYPE, "text/html; charset=UTF-8");
    //            HttpHeaders.setContentLength(res, content.readableBytes());
    //
    //            sendHttpResponse(ctx, req, res);
    //            return;
    //        }
    //
    //        if ("/favicon.ico".equals(req.getUri())) {
    //            FullHttpResponse res = new DefaultFullHttpResponse(HTTP_1_1, NOT_FOUND);
    //            sendHttpResponse(ctx, req, res);
    //            return;
    //        }

    sendHttpResponse(
        ctx, request, new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.FORBIDDEN));
    return;
  }
  @Override
  public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception {
    if (!request.getDecoderResult().isSuccess()) {
      sendError(ctx, BAD_REQUEST);
      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;
    }

    // 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;
      // we use the start time of the JVM as last modified date
      long lastModifiedSeconds = ManagementFactory.getRuntimeMXBean().getStartTime();
      if (ifModifiedSinceDateSeconds == lastModifiedSeconds) {
        sendNotModified(ctx);
        return;
      }
    }

    ClassLoader classLoader = HttpClasspathServerHandler.class.getClassLoader();
    InputStream stream = classLoader.getResourceAsStream(path);

    if (stream == null) {
      sendError(ctx, NOT_FOUND);
      return;
    }

    HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
    HttpHeaders.setContentLength(response, stream.available());
    setContentTypeHeader(response, path);
    setDateAndCacheHeaders(response);
    if (HttpHeaders.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 =
        ctx.write(new ChunkedStream(stream), ctx.newProgressivePromise());
    // Write the end marker.
    ChannelFuture lastContentFuture = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);

    // Decide whether to close the connection or not.
    if (!HttpHeaders.isKeepAlive(request)) {
      // Close the connection when the whole content is written out.
      lastContentFuture.addListener(ChannelFutureListener.CLOSE);
    }
  }
  @Override
  public void channelRead0(final ChannelHandlerContext ctx, final FullHttpRequest msg)
      throws Exception {

    final RequestHandlerMapping mapping = config.getRequestMapping(msg.getUri());

    String relativePath = msg.getUri();

    if (mapping != null) {
      relativePath = relativePath.substring(mapping.path().length());
    }

    // Create request/response
    final PooledServerRequest request = messagePool.getRequest();

    // Handle 503 - sanity check, should be caught in acceptor
    if (request == null) {
      sendServerError(ctx, new ServerTooBusyException("Maximum concurrent connections reached"));
      return;
    }

    request.init(ctx.channel(), msg, relativePath);

    final RequestHandler handler = mapping == null ? null : mapping.handler(request);

    final PooledServerResponse response = messagePool.getResponse();
    response.init(ctx, this, handler, request, config.logger());

    if (mapping == null) {
      // No handler found, 404
      response.setStatus(HttpResponseStatus.NOT_FOUND);
    }

    // Store in ChannelHandlerContext for future reference
    ctx.attr(ATTR_RESPONSE).set(response);

    try {

      // MJS: Dispatch an error if not found or authorized
      if (response.getStatus() == HttpResponseStatus.UNAUTHORIZED
          || response.getStatus() == HttpResponseStatus.NOT_FOUND) {
        config.errorHandler().onError(request, response, null);
      } else {
        handler.onRequest(request, response);
      }

    } catch (final Throwable t) {

      // Catch server errors
      response.setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR);

      try {
        config.errorHandler().onError(request, response, t);
      } catch (final Throwable t2) {
        response.write(
            t.getClass()
                + " was thrown while processing this request.  Additionally, "
                + t2.getClass()
                + " was thrown while handling this exception.");
      }

      config.logger().error(request, response, t);

      // Force request to end on exception, async handlers cannot allow
      // unchecked exceptions and still expect to return data
      if (!response.isFinished()) {
        response.finish();
      }

    } finally {

      // If handler did not request async response, finish request
      if (!response.isFinished() && !response.isSuspended()) {
        response.finish();
      }
    }
  }
  @Override
  protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception {
    // TODO Auto-generated method stub
    if (!request.getDecoderResult().isSuccess()) {
      sendError(ctx, BAD_REQUEST);
      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);
    }
  }
Beispiel #19
0
  private void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest req)
      throws SuspendExecution {
    // Handle a bad request.
    if (!req.getDecoderResult().isSuccess()) {
      sendHttpResponse(
          ctx, req, new DefaultFullHttpResponse(req.getProtocolVersion(), BAD_REQUEST), false);
      return;
    }

    final String uri = req.getUri();

    final Context actorCtx = selector.get(ctx, req);
    assert actorCtx != null;

    final ReentrantLock lock = actorCtx.getLock();
    assert lock != null;

    lock.lock();

    try {
      final ActorRef<? extends WebMessage> userActorRef = actorCtx.getRef();
      ActorImpl internalActor = (ActorImpl) actorCtx.getAttachments().get(ACTOR_KEY);

      if (userActorRef != null) {
        if (actorCtx.handlesWithWebSocket(uri)) {
          if (internalActor == null || !(internalActor instanceof WebSocketActorAdapter)) {
            //noinspection unchecked
            webSocketActor =
                new WebSocketActorAdapter(ctx, (ActorRef<? super WebMessage>) userActorRef);
            addActorToContextAndUnlock(actorCtx, webSocketActor, lock);
          }
          // Handshake
          final WebSocketServerHandshakerFactory wsFactory =
              new WebSocketServerHandshakerFactory(uri, null, true);
          handshaker = wsFactory.newHandshaker(req);
          if (handshaker == null) {
            WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel());
          } else {
            @SuppressWarnings("unchecked")
            final ActorRef<WebMessage> userActorRef0 =
                (ActorRef<WebMessage>) webSocketActor.userActor;
            handshaker
                .handshake(ctx.channel(), req)
                .addListener(
                    new GenericFutureListener<ChannelFuture>() {
                      @Override
                      public void operationComplete(ChannelFuture future) throws Exception {
                        FiberUtil.runInFiber(
                            new SuspendableRunnable() {
                              @Override
                              public void run() throws SuspendExecution, InterruptedException {
                                userActorRef0.send(
                                    new WebSocketOpened(WebActorHandler.this.webSocketActor.ref()));
                              }
                            });
                      }
                    });
          }
          return;
        } else if (actorCtx.handlesWithHttp(uri)) {
          if (internalActor == null || !(internalActor instanceof HttpActorAdapter)) {
            //noinspection unchecked
            internalActor =
                new HttpActorAdapter(
                    (ActorRef<HttpRequest>) userActorRef, actorCtx, httpResponseEncoderName);
            addActorToContextAndUnlock(actorCtx, internalActor, lock);
          }
          //noinspection unchecked
          ((HttpActorAdapter) internalActor).service(ctx, req);
          return;
        }
      }
    } finally {
      if (lock.isHeldByCurrentStrand() && lock.isLocked()) lock.unlock();
    }

    sendHttpResponse(
        ctx, req, new DefaultFullHttpResponse(req.getProtocolVersion(), NOT_FOUND), false);
  }
  @Override
  public void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
    try {
      if (msg instanceof FullHttpRequest) {
        FullHttpRequest fullRequest = (FullHttpRequest) msg;
        if (fullRequest.getUri().startsWith("/kctupload")) {

          if (fullRequest.getMethod().equals(HttpMethod.GET)) {
            // HTTP Get request!
            // Write the HTML page with the form
            writeMenu(ctx);
          } else if (fullRequest.getMethod().equals(HttpMethod.POST)) {
            /*
                 * HTTP Post request! Handle the uploaded form
                 * HTTP parameters:

            /kctupload
            username (should match player's Minecraft name)
            language (java, python, etc)
            jsonfile (a file upload, or empty)
            sourcefile (a file upload, or empty)
            jsontext (a JSON string, or empty)
            sourcetext (code as a String, or empty)
                 */

            String language = null;
            String playerName = null;
            String client = null;
            String jsonText = null;
            String sourceText = null;
            Map<String, UploadedFile> files = new LinkedHashMap<String, UploadedFile>();

            HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(fullRequest);
            try {
              logger.trace("is multipart? " + decoder.isMultipart());
              while (decoder.hasNext()) {
                InterfaceHttpData data = decoder.next();
                if (data == null) continue;

                try {
                  if (data.getHttpDataType() == HttpDataType.Attribute) {
                    Attribute attribute = (Attribute) data;
                    String name = attribute.getName();
                    String value = attribute.getValue();
                    logger.trace(String.format("http attribute: %s => %s", name, value));
                    if (name.equals("language")) {
                      language = value;
                    } else if (name.equals("playerName")) {
                      playerName = value;
                    } else if (name.equals("client")) {
                      client = value;
                    } else if (name.equals("jsontext")) {
                      jsonText = value;
                    } else if (name.equals("sourcetext")) {
                      sourceText = value;
                    } else {
                      logger.warn(
                          String.format("Unknown kctupload attribute: %s => %s", name, value));
                    }
                  } else if (data.getHttpDataType() == HttpDataType.FileUpload) {
                    // Handle file upload
                    // We may have json, source, or both
                    FileUpload fileUpload = (FileUpload) data;
                    logger.debug(
                        String.format(
                            "http file upload name %s, filename: ",
                            data.getName(), fileUpload.getFilename()));
                    String filename = fileUpload.getFilename();
                    ByteBuf buf = fileUpload.getByteBuf();
                    String fileBody = new String(buf.array(), "UTF-8");
                    files.put(data.getName(), new UploadedFile(filename, fileBody));
                  }
                } finally {
                  data.release();
                }
              }
            } finally {
              if (decoder != null) {
                // clean up resources
                decoder.cleanFiles();
                decoder.destroy();
              }
            }

            /*
             * Error checking here makes the most sense, since we can send back a reasonable error message
             * to the uploading client at this point. Makes less sense to wait to compile.
             *
             * Upload possibilities:
             *
             * bluej: file1, file2, etc. All source code. Language should be set to Java.
             * Convert to JSON, then to KCTScript. Signal an error if one happens.
             *
             * web: jsontext and/or sourcetext. json-only is OK; source-only is OK if it's Java.
             * Cannot send source-only for non-Java languages, since we can't build them (yet).
             *
             * anything else: convert to Json and hope for the best
             */
            try {
              KCTUploadHook hook = new KCTUploadHook();
              StringBuilder res = new StringBuilder();

              if (playerName == null || playerName.equals("")) {
                // XXX How do we know that the playerName is valid?
                // TODO: authenticate against Mojang's server?
                throw new TurtleException("You must specify your MineCraft player name!");
              }

              if (client == null) {
                throw new TurtleException(
                    "Your uploading and submission system must specify "
                        + "the type of client used for the upload (i.e. bluej, web, pykc, etc)");
              }

              hook.setPlayerName(playerName);
              res.append(
                  String.format("Hello %s! Thanks for using KnoxCraft Turtles\n\n", playerName));

              TurtleCompiler turtleCompiler = new TurtleCompiler(logger);
              int success = 0;
              int failure = 0;
              if (client.equalsIgnoreCase("web")
                  || client.equalsIgnoreCase("testclient")
                  || client.startsWith("pykc")) {
                // WEB OR PYTHON UPLOAD
                logger.trace("Upload from web");
                // must have both Json and source, either in text area or as uploaded files
                // XXX Conlfict of comments of the top and here??? What do we need both/ only JSon?
                // Is there a want we want, thus forcing it
                if (sourceText != null && jsonText != null) {
                  KCTScript script = turtleCompiler.parseFromJson(jsonText);
                  script.setLanguage(language);
                  script.setSourceCode(sourceText);
                  res.append(
                      String.format(
                          "Successfully uploaded KnoxCraft Turtle program "
                              + "named %s, in programming language %s\n",
                          script.getScriptName(), script.getLanguage()));
                  success++;
                  hook.addScript(script);
                } else if (files.containsKey("jsonfile") && files.containsKey("sourcefile")) {
                  UploadedFile sourceUpload = files.get("sourcefile");
                  UploadedFile jsonUpload = files.get("jsonfile");
                  KCTScript script = turtleCompiler.parseFromJson(jsonUpload.body);
                  script.setLanguage(language);
                  script.setSourceCode(sourceUpload.body);
                  res.append(
                      String.format(
                          "Successfully uploaded KnoxCraft Turtle program "
                              + "named %s, in programming language %s\n",
                          script.getScriptName(), script.getLanguage()));
                  success++;
                  hook.addScript(script);
                } else {
                  throw new TurtleException(
                      "You must upload BOTH json and the corresponding source code "
                          + " (either as files or pasted into the text areas)");
                }
              } else if ("bluej".equalsIgnoreCase(client)) {
                // BLUEJ UPLOAD
                logger.trace("Upload from bluej");
                for (Entry<String, UploadedFile> entry : files.entrySet()) {
                  try {
                    UploadedFile uploadedFile = entry.getValue();
                    res.append(
                        String.format(
                            "Trying to upload and compile file %s\n", uploadedFile.filename));
                    logger.trace(
                        String.format(
                            "Trying to upload and compile file %s\n", uploadedFile.filename));
                    KCTScript script =
                        turtleCompiler.compileJavaTurtleCode(
                            uploadedFile.filename, uploadedFile.body);
                    logger.trace("Returned KCTScript (it's JSON is): " + script.toJSONString());
                    hook.addScript(script);
                    res.append(
                        String.format(
                            "Successfully uploaded file %s and compiled KnoxCraft Turtle program "
                                + "named %s in programming language %s\n\n",
                            uploadedFile.filename, script.getScriptName(), script.getLanguage()));
                    success++;
                  } catch (TurtleCompilerException e) {
                    logger.warn("Unable to compile Turtle code", e);
                    res.append(String.format("%s\n\n", e.getMessage()));
                    failure++;
                  } catch (TurtleException e) {
                    logger.error("Error in compiling (possibly a server side error)", e);
                    res.append(
                        String.format("Unable to process Turtle code %s\n\n", e.getMessage()));
                    failure++;
                  } catch (Exception e) {
                    logger.error("Unexpected error compiling Turtle code to KCTScript", e);
                    failure++;
                    res.append(String.format("Failed to load script %s\n", entry.getKey()));
                  }
                }
              } else {
                // UNKNOWN CLIENT UPLOAD
                // TODO Unknown client; make a best effort to handle upload
                res.append(
                    String.format(
                        "Unknown upload client: %s; making our best effort to handle the upload"));
              }

              res.append(
                  String.format(
                      "\nSuccessfully uploaded %d KnoxCraft Turtles programs\n", success));
              if (failure > 0) {
                res.append(
                    String.format("\nFailed to upload %d KnoxCraft Turtles programs\n", failure));
              }
              Canary.hooks().callHook(hook);
              writeResponse(ctx.channel(), fullRequest, res.toString(), client);
            } catch (TurtleException e) {
              // XXX can this still happen? Don't we catch all of these?
              writeResponse(ctx.channel(), fullRequest, e.getMessage(), "error");
            }
          }
        }
      }
    } catch (Exception e) {
      logger.error("Internal Server Error: Channel error", e);
      throw e;
    }
  }