Esempio n. 1
0
  public static boolean isModified(String etag, long last, HttpRequest nettyRequest) {

    if (nettyRequest.containsHeader(IF_NONE_MATCH)) {
      final String browserEtag = nettyRequest.getHeader(IF_NONE_MATCH);
      if (browserEtag.equals(etag)) {
        return false;
      }
      return true;
    }

    if (nettyRequest.containsHeader(IF_MODIFIED_SINCE)) {
      final String ifModifiedSince = nettyRequest.getHeader(IF_MODIFIED_SINCE);

      if (!StringUtils.isEmpty(ifModifiedSince)) {
        try {
          Date browserDate = Utils.getHttpDateFormatter().parse(ifModifiedSince);
          if (browserDate.getTime() >= last) {
            return false;
          }
        } catch (ParseException ex) {
          Logger.warn("Can't parse HTTP date", ex);
        }
        return true;
      }
    }
    return true;
  }
Esempio n. 2
0
 private static FilteredPipeline findAccepting(final HttpRequest request) {
   final FilteredPipeline candidate = null;
   for (final FilteredPipeline f : pipelines) {
     if (f.checkAccepts(request)) {
       return f;
     }
   }
   if (request.getHeader(HttpHeaders.Names.HOST).contains("amazonaws.com")
       || request.getHeader(HttpHeaders.Names.HOST).contains(subDomain.get())) {
     String hostHeader = request.getHeader(HttpHeaders.Names.HOST);
     LOG.debug("Trying to intercept request for " + hostHeader);
     for (final FilteredPipeline f : pipelines) {
       if (Ats.from(f).has(ComponentPart.class)) {
         Class<? extends ComponentId> compIdClass = Ats.from(f).get(ComponentPart.class).value();
         ComponentId compId = ComponentIds.lookup(compIdClass);
         if (Ats.from(compIdClass).has(PublicService.class)) {
           if (request.getHeaderNames().contains("SOAPAction")
               && f.addHandlers(Channels.pipeline()).get(SoapHandler.class) == null) {
             continue; // Skip pipeline which doesn't handle SOAP for this SOAP request
           } else if (!request.getHeaderNames().contains("SOAPAction")
               && f.addHandlers(Channels.pipeline()).get(SoapHandler.class) != null) {
             continue; // Skip pipeline which handles SOAP for this non-SOAP request
           }
           LOG.debug("Maybe intercepting: " + hostHeader + " using " + f.getClass());
           if (Ats.from(compIdClass).has(AwsServiceName.class)
               && request
                   .getHeader(HttpHeaders.Names.HOST)
                   .matches(
                       "[\\w\\.-_]*" + compId.getAwsServiceName() + "\\.\\w+\\.amazonaws.com")) {
             return f; // Return pipeline which can handle the request for
                       // ${service}.${region}.amazonaws.com
           } else if (request
               .getHeader(HttpHeaders.Names.HOST)
               .matches("[\\w\\.-_]*" + compId.name() + "\\." + subDomain.get())) {
             return f; // Return pipeline which can handle the request for
                       // ${service}.${system.dns.dnsdomain}
           }
         }
       }
     }
   }
   if (candidate == null) {
     for (final FilteredPipeline f : internalPipelines) {
       if (f.checkAccepts(request)) {
         return f;
       }
     }
   }
   return candidate;
 }
Esempio n. 3
0
  protected static void addToRequest(HttpRequest nettyRequest, Request request) {
    for (String key : nettyRequest.getHeaderNames()) {
      Http.Header hd = new Http.Header();
      hd.name = key.toLowerCase();
      hd.values = new ArrayList<String>();
      for (String next : nettyRequest.getHeaders(key)) {
        hd.values.add(next);
      }
      request.headers.put(hd.name, hd);
    }

    String value = nettyRequest.getHeader(COOKIE);
    if (value != null) {
      Set<Cookie> cookies = new CookieDecoder().decode(value);
      if (cookies != null) {
        for (Cookie cookie : cookies) {
          Http.Cookie playCookie = new Http.Cookie();
          playCookie.name = cookie.getName();
          playCookie.path = cookie.getPath();
          playCookie.domain = cookie.getDomain();
          playCookie.secure = cookie.isSecure();
          playCookie.value = cookie.getValue();
          playCookie.httpOnly = cookie.isHttpOnly();
          request.cookies.put(playCookie.name, playCookie);
        }
      }
    }
  }
Esempio n. 4
0
  @Override
  public void messageReceived(ChannelHandlerContext ctx, MessageEvent me) throws Exception {
    if (!(me.getMessage() instanceof HttpRequest)) {
      ctx.sendUpstream(me);
      return;
    }

    HttpRequest request = (HttpRequest) me.getMessage();
    Object response;

    // Look up resource
    String path = request.getUri();
    String host = request.getHeader("host");
    log.debug("Received request for path:" + path);

    boolean showHtml = false;
    if (path.endsWith("?html")) {
      showHtml = true;
      path = path.replace("?html", "");
    }

    for (String service : resources.keySet()) {
      log.debug("Available Service: " + service);
    }

    Model model = resources.get(path);

    if (model != null) {
      if (request.getMethod() == HttpMethod.GET) {
        if (showHtml) {
          String html = HtmlCreator.createModelPage(model, new URI(path), host);
          response = ChannelBuffers.wrappedBuffer(html.getBytes(Charset.forName("UTF-8")));

          log.debug("Returned html page for resource: " + path);
        } else {
          response = new SelfDescription(model, new URI(request.getUri()));

          log.debug("Resource found: " + path);
        }
      } else {
        response =
            new DefaultHttpResponse(
                request.getProtocolVersion(), HttpResponseStatus.METHOD_NOT_ALLOWED);

        log.debug("Method not allowed: " + request.getMethod());
      }
    } else {
      response =
          HttpResponseFactory.createHttpResponse(
              request.getProtocolVersion(), HttpResponseStatus.NOT_FOUND);

      log.debug("Resource not found: " + path);
    }

    // Send response
    ChannelFuture future = Channels.write(ctx.getChannel(), response);
    future.addListener(ChannelFutureListener.CLOSE);
  }
Esempio n. 5
0
  public HttpResponse generateResponse(HttpRequest request, String serverOrigin) throws Exception {

    HttpResponse response =
        new DefaultHttpResponse(
            HttpVersion.HTTP_1_1,
            new HttpResponseStatus(101, "Web Socket Protocol Handshake - IETF-00"));
    response.addHeader(HttpHeaders.Names.CONNECTION, "Upgrade");
    response.addHeader(HttpHeaders.Names.UPGRADE, "WebSocket");
    String origin = request.getHeader(Names.ORIGIN);
    if (origin == null) {
      origin = serverOrigin;
    }
    response.addHeader(Names.SEC_WEBSOCKET_ORIGIN, origin);
    response.addHeader(Names.SEC_WEBSOCKET_LOCATION, getWebSocketLocation(request));

    String protocol = request.getHeader(Names.SEC_WEBSOCKET_PROTOCOL);

    if (protocol != null) {
      response.addHeader(Names.SEC_WEBSOCKET_PROTOCOL, protocol);
    }

    // Calculate the answer of the challenge.
    String key1 = request.getHeader(Names.SEC_WEBSOCKET_KEY1);
    String key2 = request.getHeader(Names.SEC_WEBSOCKET_KEY2);
    byte[] key3 = new byte[8];

    request.getContent().readBytes(key3);

    byte[] solution = WebSocketChallenge00.solve(key1, key2, key3);

    ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(solution.length + 2);
    buffer.writeBytes(solution);

    response.addHeader("Content-Length", buffer.readableBytes());

    response.setContent(buffer);
    response.setChunked(false);

    return response;
  }
Esempio n. 6
0
 @Override
 public boolean checkAccepts(final HttpRequest message) {
   if (message instanceof MappingHttpRequest) {
     final MappingHttpRequest httpRequest = (MappingHttpRequest) message;
     final boolean usesServicePath =
         Iterables.any(servicePathPrefixes, Strings.isPrefixOf(message.getUri()));
     final boolean noPath =
         message.getUri().isEmpty()
             || message.getUri().equals("/")
             || message.getUri().startsWith("/?");
     if (!usesServicePath
         && !(noPath && resolvesByHost(message.getHeader(HttpHeaders.Names.HOST)))) {
       return false;
     }
     if (httpRequest.getMethod().equals(HttpMethod.POST)
         && !message.getHeaderNames().contains("SOAPAction")) {
       Map<String, String> parameters = new HashMap<String, String>(httpRequest.getParameters());
       Set<String> nonQueryParameters = Sets.newHashSet();
       final String query = httpRequest.getContentAsString();
       for (String p : query.split("&")) {
         String[] splitParam = p.split("=", 2);
         String lhs = splitParam[0];
         String rhs = splitParam.length == 2 ? splitParam[1] : null;
         try {
           if (lhs != null) lhs = new URLCodec().decode(lhs);
         } catch (DecoderException e) {
         }
         try {
           if (rhs != null) rhs = new URLCodec().decode(rhs);
         } catch (DecoderException e) {
         }
         parameters.put(lhs, rhs);
         nonQueryParameters.add(lhs);
       }
       for (RequiredQueryParams p : requiredQueryParams) {
         if (!parameters.containsKey(p.toString())) {
           return false;
         }
       }
       httpRequest.getParameters().putAll(parameters);
       httpRequest.addNonQueryParameterKeys(nonQueryParameters);
     } else {
       for (RequiredQueryParams p : requiredQueryParams) {
         if (!httpRequest.getParameters().containsKey(p.toString())) {
           return false;
         }
       }
     }
     return true;
   }
   return false;
 }
  private void writeResponse(MessageEvent e, RequestV2 request, InetAddress ia) {
    // Decide whether to close the connection or not.
    boolean close =
        HttpHeaders.Values.CLOSE.equalsIgnoreCase(
                nettyRequest.getHeader(HttpHeaders.Names.CONNECTION))
            || nettyRequest.getProtocolVersion().equals(HttpVersion.HTTP_1_0)
                && !HttpHeaders.Values.KEEP_ALIVE.equalsIgnoreCase(
                    nettyRequest.getHeader(HttpHeaders.Names.CONNECTION));

    // Build the response object.
    HttpResponse response;
    if (request.getLowRange() != 0 || request.getHighRange() != 0) {
      response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.PARTIAL_CONTENT);
    } else {
      String soapAction = nettyRequest.getHeader("SOAPACTION");

      if (soapAction != null && soapAction.contains("X_GetFeatureList")) {
        LOGGER.debug("Invalid action in SOAPACTION: " + soapAction);
        response =
            new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR);
      } else {
        response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
      }
    }

    StartStopListenerDelegate startStopListenerDelegate =
        new StartStopListenerDelegate(ia.getHostAddress());

    try {
      request.answer(response, e, close, startStopListenerDelegate);
    } catch (IOException e1) {
      LOGGER.trace("HTTP request V2 IO error: " + e1.getMessage());
      // note: we don't call stop() here in a finally block as
      // answer() is non-blocking. we only (may) need to call it
      // here in the case of an exception. it's a no-op if it's
      // already been called
      startStopListenerDelegate.stop();
    }
  }
Esempio n. 8
0
  void saveExceededSizeError(HttpRequest nettyRequest, Request request, Response response) {

    String warning = nettyRequest.getHeader(HttpHeaders.Names.WARNING);
    String length = nettyRequest.getHeader(HttpHeaders.Names.CONTENT_LENGTH);
    if (warning != null) {
      Logger.trace("saveExceededSizeError: begin");
      try {
        StringBuilder error = new StringBuilder();
        error.append("\u0000");
        // Cannot put warning which is play.netty.content.length.exceeded
        // as Key as it will result error when printing error
        error.append("play.netty.maxContentLength");
        error.append(":");
        String size = null;
        try {
          size = JavaExtensions.formatSize(Long.parseLong(length));
        } catch (Exception e) {
          size = length + " bytes";
        }
        error.append(Messages.get(warning, size));
        error.append("\u0001");
        error.append(size);
        error.append("\u0000");
        if (request.cookies.get(Scope.COOKIE_PREFIX + "_ERRORS") != null
            && request.cookies.get(Scope.COOKIE_PREFIX + "_ERRORS").value != null) {
          error.append(request.cookies.get(Scope.COOKIE_PREFIX + "_ERRORS").value);
        }
        String errorData = URLEncoder.encode(error.toString(), "utf-8");
        Http.Cookie c = new Http.Cookie();
        c.value = errorData;
        c.name = Scope.COOKIE_PREFIX + "_ERRORS";
        request.cookies.put(Scope.COOKIE_PREFIX + "_ERRORS", c);
        Logger.trace("saveExceededSizeError: end");
      } catch (Exception e) {
        throw new UnexpectedException("Error serialization problem", e);
      }
    }
  }
Esempio n. 9
0
  @Override
  public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
    HttpRequest request = (HttpRequest) e.getMessage();

    if (request.getContent().readableBytes() == 0) {
      BaseTransport.respond(e.getChannel(), INTERNAL_SERVER_ERROR, "Payload expected.");
      return;
    }

    transportMetrics.messagesReceived.mark();
    transportMetrics.messagesReceivedSize.update(request.getContent().readableBytes());

    // logger.debug("Received {}", request.getContent().toString(CharsetUtil.UTF_8));

    String contentTypeHeader = request.getHeader(CONTENT_TYPE);
    if (contentTypeHeader == null) {
      contentTypeHeader = BaseTransport.CONTENT_TYPE_PLAIN;
    }

    String decodedContent;
    if (BaseTransport.CONTENT_TYPE_FORM.equals(contentTypeHeader)) {
      QueryStringDecoder decoder =
          new QueryStringDecoder("?" + request.getContent().toString(CharsetUtil.UTF_8));
      List<String> d = decoder.getParameters().get("d");
      if (d == null) {
        BaseTransport.respond(e.getChannel(), INTERNAL_SERVER_ERROR, "Payload expected.");
        return;
      }
      decodedContent = d.get(0);
    } else {
      decodedContent = request.getContent().toString(CharsetUtil.UTF_8);
    }

    if (decodedContent.length() == 0) {
      BaseTransport.respond(e.getChannel(), INTERNAL_SERVER_ERROR, "Payload expected.");
      return;
    }

    String[] messages = MAPPER.readValue(decodedContent, String[].class);
    for (String message : messages) {
      SockJsMessage jsMessage = new SockJsMessage(message);
      ctx.sendUpstream(new UpstreamMessageEvent(e.getChannel(), jsMessage, e.getRemoteAddress()));
    }

    if (isJsonpEnabled) {
      BaseTransport.respond(e.getChannel(), OK, "ok");
    } else {
      BaseTransport.respond(e.getChannel(), NO_CONTENT, "");
    }
  }
Esempio n. 10
0
 /**
  * adds a TxnId if one is not already set.
  *
  * @param request
  * @return
  */
 public static HttpRequest addTxnId(HttpRequest request) {
   if (request.getHeader("Strest-Txn-Id") == null)
     request.setHeader("Strest-Txn-Id", generateTxnId());
   return request;
 }
 private String getWebSocketLocation(HttpRequest req) {
   return "ws://" + req.getHeader(HttpHeaders.Names.HOST) + WEBSOCKET_PATH;
 }
Esempio n. 12
0
  /** Expected Message types: - HTTP Requests */
  @Override
  public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {

    if (!(e.getMessage() instanceof HttpRequest)) {
      super.messageReceived(ctx, e);
      return;
    }

    HttpRequest httpRequest = (HttpRequest) e.getMessage();
    URI targetUri =
        toThing(URI.create("http://" + httpRequest.getHeader("HOST") + httpRequest.getUri()));

    log.debug("Received HTTP request for " + targetUri);

    if (httpRequest.getHeader("HOST").contains(DNS_WILDCARD_POSTFIX)) {
      String targetUriHost = InetAddress.getByName(targetUri.getHost()).getHostAddress();
      // remove leading zeros per block
      targetUriHost = targetUriHost.replaceAll(":0000", ":0");
      targetUriHost = targetUriHost.replaceAll(":000", ":0");
      targetUriHost = targetUriHost.replaceAll(":00", ":0");
      targetUriHost = targetUriHost.replaceAll("(:0)([ABCDEFabcdef123456789])", ":$2");

      // return shortened IP
      targetUriHost =
          targetUriHost.replaceAll("((?:(?:^|:)0\\b){2,}):?(?!\\S*\\b\\1:0\\b)(\\S*)", "::$2");
      log.debug("Target host: " + targetUriHost);

      String targetUriPath = targetUri.getRawPath();
      log.debug("Target path: " + targetUriPath);

      if (IPAddressUtil.isIPv6LiteralAddress(targetUriHost)) {
        targetUriHost = "[" + targetUriHost + "]";
      }

      targetUri = toThing(URI.create("http://" + targetUriHost + httpRequest.getUri()));
      log.debug("Shortened target URI: " + targetUri);
    }

    URI uriToCheck = targetUri;
    if ((uriToCheck.getQuery() != null) && (uriToCheck.getQuery().equals("html"))) {
      uriToCheck = toThing(URI.create("http://" + targetUri.getHost() + targetUri.getPath()));
    }

    if (entities.containsKey(uriToCheck)) {
      Backend backend = entities.get(uriToCheck);
      try {
        ctx.getPipeline().remove("Backend to handle request");
      } catch (NoSuchElementException ex) {
        // Fine. There was no handler to be removed.
      }
      ctx.getPipeline().addLast("Backend to handle request", backend);
      log.debug("Forward request to " + backend);
    } else if (virtualEntities.containsKey(uriToCheck)) {
      Backend backend = virtualEntities.get(uriToCheck);
      try {
        ctx.getPipeline().remove("Backend to handle request");
      } catch (NoSuchElementException ex) {
        // Fine. There was no handler to be removed.
      }
      ctx.getPipeline().addLast("Backend to handle request", backend);
      log.debug("Forward request to " + backend);
    }

    //        else if (targetUriPath.equals(PATH_TO_SERVER_LIST)) {
    //            // Handle request for resource at path ".well-known/core"
    //            StringBuilder buf = new StringBuilder();
    //            for(URI entity: getServices()) {
    //                buf.append(toThing(entity).toString() + "\n");
    //            }
    //            Channels.write(ctx.getChannel(),
    // Answer.create(buf.toString()).setMime("text/plain"));
    //            return;
    //        }

    //        else if("/visualizer".equals(targetUriPath)){
    //            try {
    //                ctx.getPipeline().remove("Backend to handle request");
    //            }
    //            catch(NoSuchElementException ex) {
    //                //Fine. There was no handler to be removed.
    //            }
    //            ctx.getPipeline().addLast("VisualizerService", VisualizerService.getInstance());
    //            log.debug("Forward request to visualizer.");
    //        }

    /*else if(targetUriPath.startsWith(SERVER_PATH_TO_SLSE_UI)) {
    	String f = LOCAL_PATH_TO_SLSE_UI + targetUriPath.substring(SERVER_PATH_TO_SLSE_UI.length());
    	Channels.write(ctx.getChannel(), Answer.create(new File(f)).setMime("text/n3"));
    }*/

    else if ("/".equals(targetUri.getRawPath())) {
      HttpResponse httpResponse =
          new DefaultHttpResponse(httpRequest.getProtocolVersion(), HttpResponseStatus.OK);

      httpResponse.setContent(getHtmlListOfServices());
      ChannelFuture future = Channels.write(ctx.getChannel(), httpResponse);
      future.addListener(ChannelFutureListener.CLOSE);
      return;
    } else if (httpRequest.getUri().endsWith("spitfire-logo.png")
        || (httpRequest.getUri().endsWith("favicon.ico"))) {
      File img;
      if (httpRequest.getUri().endsWith("spitfire-logo.png")) {
        img = new File("spitfire-logo.png");
      } else {
        img = new File("favicon.ico");
      }

      int imgLength = (int) img.length();

      FileInputStream in = new FileInputStream(img);
      byte[] imgMemory = new byte[imgLength];
      in.read(imgMemory);
      in.close();

      HttpResponse httpResponse =
          new DefaultHttpResponse(httpRequest.getProtocolVersion(), HttpResponseStatus.OK);
      httpResponse.setContent(ChannelBuffers.wrappedBuffer(imgMemory));
      ChannelFuture future = Channels.write(ctx.getChannel(), httpResponse);
      future.addListener(ChannelFutureListener.CLOSE);

      if (httpRequest.getUri().endsWith("spitfire-logo.png")) {
        log.debug("Served request for Spitfire image.");
      } else {
        log.debug("Served favicon.");
      }

      return;
    }

    ctx.sendUpstream(e);
  }
Esempio n. 13
0
  private void handleHttpRequest(ChannelHandlerContext ctx, HttpRequest req, MessageEvent e)
      throws Exception {
    /* 获取请求头中的cookie字段 */
    String cookieInReqHeader = req.getHeader(COOKIE);

    /*
     * 根据URL地址判断当前的请求处理方式
     *      1.如果URL为ServerHandler.ROOT_DIR,那么处理用户登录过程
     *      2.如果URL为WebSocketHandler.WEBSOCKET_PATH,则处理连接WebSocket建立过程
     *      3.........(等待后续添加)
     */
    if (req.getUri().equals(ServerHandler.ROOT_DIR)) // 判断URL为根目录地址
    {
      HttpResponse res = new DefaultHttpResponse(HTTP_1_1, OK);

      /*
       * 判断当前请求头中的cookie是否为空
       * 如果为空,需要强制要求浏览器设置cookie
       */
      if (cookieInReqHeader == null) {
        String sessionId = Session.produceSessionId();
        ServerHandler.sessionManager.add(
            new Session(sessionId, Session.INDEX, ctx.getChannel().getId()));
        ChannelBuffer content = ServerWritePage.getContent(Session.INDEX);
        buildResponse(res, true, sessionId, content, content.readableBytes());
        sendHttpResponse(ctx, req, res);
      } else {
        /* 即使浏览器请求头中的cookie不为空
         * 可能服务器的Session集合中并不包含对应的cookie,此时仍然需要强制浏览器重设cookie
         */
        if (!ServerHandler.sessionManager.contain(cookieInReqHeader)) {
          String sessionId = Session.produceSessionId();
          ServerHandler.sessionManager.add(
              new Session(sessionId, Session.INDEX, ctx.getChannel().getId()));
          ChannelBuffer content = ServerWritePage.getContent(Session.INDEX);
          buildResponse(res, true, sessionId, content, content.readableBytes());
          sendHttpResponse(ctx, req, res);
        } else {
          int sessionState = ServerHandler.sessionManager.find(cookieInReqHeader).getCurrentState();
          if (sessionState == Session.INDEX) // 判断当前的Session状态是否为登录页面状态
          {
            if (req.getMethod() == GET) // 如果当前网页被重复刷新,需要始终维持此Session并向用户送回登陆页面
            {
              ServerHandler.sessionManager.sessionActiveTimeUpdate(cookieInReqHeader);
              ChannelBuffer content = ServerWritePage.getContent(Session.INDEX);
              buildResponse(res, false, null, content, content.readableBytes());
              sendHttpResponse(ctx, req, res);
            }
            if (req.getMethod() == POST) // 如果用户点击了登录按钮
            {
              HashMap<String, String> parameterList = getPostParameter(req); // 获取POST请求参数
              if (parameterList.get("navigatorName").equals("Firefox")
                  || parameterList.get("navigatorName").equals("Chrome")
                  || parameterList
                      .get("navigatorName")
                      .equals("Safari")) // 暂时简单判断浏览器版本,并根据浏览器版本发回连接建立页面
              {
                try {
                  // session的状态和活动时间都被相继更新
                  ServerHandler.sessionManager.sessionStateUpdate(
                      cookieInReqHeader, Session.WEBSOCKET);
                  ServerHandler.sessionManager.sessionActiveTimeUpdate(cookieInReqHeader);
                  ChannelBuffer content = ServerWritePage.getContent(Session.WEBSOCKET);
                  buildResponse(res, false, null, content, content.readableBytes());
                  sendHttpResponse(ctx, req, res);
                } catch (Exception a) {
                  a.printStackTrace();
                }
              } else // 根据其他浏览器版本选择 long Polling或者streaming方式同样建立连接
              {
                /* To deal with long polling and streaming */
                /* To send back the correspondent page */
              }
            }
          } else if (sessionState == Session.WEBSOCKET) // 当前的Session状态是否为WebSocket连接建立状态
          {
            /*
             * 如果已经是连接建立状态,但用户刷新了此页面,此时仍然需要维持Session
             * WebSocket连接已经建立的情况下,刷新页面之后用户将不需要重新登录
             * 但是先前的WebSocket连接将被强制关闭,并且重新发出新的连接建立请求
             * 即强制一个用户只能向服务器请求一条WebSocket连接
             */
            if (req.getMethod() == GET) {
              if (ServerHandler.clientChannelGroup.find(
                      ServerHandler.sessionManager.find(cookieInReqHeader).getChannelId())
                  != null) {
                ServerHandler.clientChannelGroup
                    .find(ServerHandler.sessionManager.find(cookieInReqHeader).getChannelId())
                    .close();
              }
              ServerHandler.sessionManager.sessionActiveTimeUpdate(cookieInReqHeader);
              ChannelBuffer content = ServerWritePage.getContent(Session.WEBSOCKET);
              buildResponse(res, false, null, content, content.readableBytes());
              sendHttpResponse(ctx, req, res);
            }
          }
        }
      }

    } else if (req.getUri().equals(WebSocketHandler.WEBSOCKET_PATH)) // 根据地址判断WebSocket请求是否被发送
    {
      ServerHandler.sessionManager.sessionChannelIdUpdate(
          cookieInReqHeader, ctx.getChannel().getId());
      ctx.getPipeline()
          .addLast("websocket", new WebSocketHandler()); // 将WebSocketHandler加入到当前的Pipeline中
      ctx.getPipeline().remove(this); // 将当前的Handler移除掉
      ctx.sendUpstream(e); // 将Pipeline中的事件传递到WebSocketHandler中
      ServerHandler.clientChannelGroup.add(ctx.getChannel()); // 并且将当前的Channel加入到Group中
    } else { // 如果请求到了其他地址,发回请求地址无法响应的回复
      HttpResponse res = new DefaultHttpResponse(HTTP_1_1, NOT_FOUND);
      sendHttpResponse(ctx, req, res);
      return;
    }
  }
Esempio n. 14
0
  @Test
  public void testValidRoutePatterns() throws Exception {
    HttpRequest modifiedReq = testPattern("/metrics/:metricId", "/metrics/foo");
    Assert.assertTrue(testRouteHandlerCalled);
    Assert.assertEquals(1, modifiedReq.getHeaders().size());
    Assert.assertEquals("metricId", modifiedReq.getHeaders().get(0).getKey());
    Assert.assertEquals("foo", modifiedReq.getHeaders().get(0).getValue());
    testRouteHandlerCalled = false;

    modifiedReq =
        testPattern("/tenants/:tenantId/entities/:entityId", "/tenants/acFoo/entities/enBar");
    Assert.assertTrue(testRouteHandlerCalled);
    Assert.assertEquals(2, modifiedReq.getHeaders().size());
    Assert.assertTrue(modifiedReq.getHeader("tenantId").equals("acFoo"));
    Assert.assertTrue(modifiedReq.getHeader("entityId").equals("enBar"));
    testRouteHandlerCalled = false;

    modifiedReq =
        testPattern(
            "/tenants/:tenantId/entities/:entityId/checks/:checkId/metrics/:metricId/plot",
            "/tenants/acFoo/entities/enBar/checks/chFoo/metrics/myMetric/plot");
    Assert.assertTrue(testRouteHandlerCalled);
    Assert.assertEquals(4, modifiedReq.getHeaders().size());
    Assert.assertTrue(modifiedReq.getHeader("tenantId").equals("acFoo"));
    Assert.assertTrue(modifiedReq.getHeader("entityId").equals("enBar"));
    Assert.assertTrue(modifiedReq.getHeader("entityId").equals("enBar"));
    Assert.assertTrue(modifiedReq.getHeader("checkId").equals("chFoo"));
    Assert.assertTrue(modifiedReq.getHeader("metricId").equals("myMetric"));
    testRouteHandlerCalled = false;

    modifiedReq = testPattern("/software/:name/:version", "/software/blueflood/v0.1");
    Assert.assertTrue(testRouteHandlerCalled);
    Assert.assertEquals(2, modifiedReq.getHeaders().size());
    Assert.assertTrue(modifiedReq.getHeader("name").equals("blueflood"));
    Assert.assertTrue(modifiedReq.getHeader("version").equals("v0.1"));
    testRouteHandlerCalled = false;

    // trailing slash
    modifiedReq = testPattern("/software/:name/:version/", "/software/blueflood/v0.1/");
    Assert.assertTrue(testRouteHandlerCalled);
    Assert.assertEquals(2, modifiedReq.getHeaders().size());
    Assert.assertTrue(modifiedReq.getHeader("name").equals("blueflood"));
    Assert.assertTrue(modifiedReq.getHeader("version").equals("v0.1"));
    testRouteHandlerCalled = false;

    modifiedReq = testPattern("/:name/:version", "/blueflood/v0.1");
    Assert.assertTrue(testRouteHandlerCalled);
    Assert.assertEquals(2, modifiedReq.getHeaders().size());
    Assert.assertTrue(modifiedReq.getHeader("name").equals("blueflood"));
    Assert.assertTrue(modifiedReq.getHeader("version").equals("v0.1"));
    testRouteHandlerCalled = false;
  }
Esempio n. 15
0
 protected String getWebSocketLocation(HttpRequest request) {
   return "ws://" + request.getHeader(HttpHeaders.Names.HOST) + request.getUri();
 }
Esempio n. 16
0
  private void websocketHandshake(final ChannelHandlerContext ctx, HttpRequest req, MessageEvent e)
      throws Exception {

    // Create the WebSocket handshake response.
    HttpResponse res =
        new DefaultHttpResponse(
            HttpVersion.HTTP_1_1, new HttpResponseStatus(101, "Web Socket Protocol Handshake"));
    res.addHeader(HttpHeaders.Names.UPGRADE, HttpHeaders.Values.WEBSOCKET);
    res.addHeader(CONNECTION, HttpHeaders.Values.UPGRADE);

    // Fill in the headers and contents depending on handshake method.
    if (req.containsHeader(SEC_WEBSOCKET_KEY1) && req.containsHeader(SEC_WEBSOCKET_KEY2)) {
      // New handshake method with a challenge:
      res.addHeader(SEC_WEBSOCKET_ORIGIN, req.getHeader(ORIGIN));
      res.addHeader(
          SEC_WEBSOCKET_LOCATION, "ws://" + req.getHeader(HttpHeaders.Names.HOST) + req.getUri());
      String protocol = req.getHeader(SEC_WEBSOCKET_PROTOCOL);
      if (protocol != null) {
        res.addHeader(SEC_WEBSOCKET_PROTOCOL, protocol);
      }

      // Calculate the answer of the challenge.
      String key1 = req.getHeader(SEC_WEBSOCKET_KEY1);
      String key2 = req.getHeader(SEC_WEBSOCKET_KEY2);
      int a =
          (int)
              (Long.parseLong(key1.replaceAll("[^0-9]", ""))
                  / key1.replaceAll("[^ ]", "").length());
      int b =
          (int)
              (Long.parseLong(key2.replaceAll("[^0-9]", ""))
                  / key2.replaceAll("[^ ]", "").length());
      long c = req.getContent().readLong();
      ChannelBuffer input = ChannelBuffers.buffer(16);
      input.writeInt(a);
      input.writeInt(b);
      input.writeLong(c);
      try {
        ChannelBuffer output =
            ChannelBuffers.wrappedBuffer(MessageDigest.getInstance("MD5").digest(input.array()));
        res.setContent(output);
      } catch (NoSuchAlgorithmException ex) {
        throw new UnexpectedException(ex);
      }
    } else {
      // Old handshake method with no challenge:
      res.addHeader(WEBSOCKET_ORIGIN, req.getHeader(ORIGIN));
      res.addHeader(
          WEBSOCKET_LOCATION, "ws://" + req.getHeader(HttpHeaders.Names.HOST) + req.getUri());
      String protocol = req.getHeader(WEBSOCKET_PROTOCOL);
      if (protocol != null) {
        res.addHeader(WEBSOCKET_PROTOCOL, protocol);
      }
    }

    // Keep the original request
    Http.Request request = parseRequest(ctx, req);

    // Route the websocket request
    request.method = "WS";
    Map<String, String> route = Router.route(request.method, request.path);
    if (!route.containsKey("action")) {
      // No route found to handle this websocket connection
      ctx.getChannel()
          .write(new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.NOT_FOUND));
      return;
    }

    // Upgrade the connection and send the handshake response.
    ChannelPipeline p = ctx.getChannel().getPipeline();
    p.remove("aggregator");
    p.replace("decoder", "wsdecoder", new WebSocketFrameDecoder());

    // Connect
    ctx.getChannel().write(res);

    p.replace("encoder", "wsencoder", new WebSocketFrameEncoder());
    req.setMethod(new HttpMethod("WEBSOCKET"));

    // Inbound
    Http.Inbound inbound =
        new Http.Inbound() {

          @Override
          public boolean isOpen() {
            return ctx.getChannel().isOpen();
          }
        };
    channels.put(ctx, inbound);

    // Outbound
    Http.Outbound outbound =
        new Http.Outbound() {

          final List<ChannelFuture> writeFutures =
              Collections.synchronizedList(new ArrayList<ChannelFuture>());
          Promise<Void> closeTask;

          synchronized void writeAndClose(ChannelFuture writeFuture) {
            if (!writeFuture.isDone()) {
              writeFutures.add(writeFuture);
              writeFuture.addListener(
                  new ChannelFutureListener() {

                    public void operationComplete(ChannelFuture cf) throws Exception {
                      writeFutures.remove(cf);
                      futureClose();
                    }
                  });
            }
          }

          void futureClose() {
            if (closeTask != null && writeFutures.isEmpty()) {
              closeTask.invoke(null);
            }
          }

          @Override
          public void send(String data) {
            if (!isOpen()) {
              throw new IllegalStateException("The outbound channel is closed");
            }
            writeAndClose(ctx.getChannel().write(new DefaultWebSocketFrame(data)));
          }

          @Override
          public void send(byte opcode, byte[] data, int offset, int length) {
            if (!isOpen()) {
              throw new IllegalStateException("The outbound channel is closed");
            }
            writeAndClose(
                ctx.getChannel()
                    .write(new DefaultWebSocketFrame(opcode, wrappedBuffer(data, offset, length))));
          }

          @Override
          public synchronized boolean isOpen() {
            return ctx.getChannel().isOpen() && closeTask == null;
          }

          @Override
          public synchronized void close() {
            closeTask = new Promise<Void>();
            closeTask.onRedeem(
                new Action<Promise<Void>>() {

                  public void invoke(Promise<Void> completed) {
                    writeFutures.clear();
                    ctx.getChannel().disconnect();
                    closeTask = null;
                  }
                });
            futureClose();
          }
        };

    Invoker.invoke(new WebSocketInvocation(route, request, inbound, outbound, ctx, e));
  }
Esempio n. 17
0
  private void handleHttpRequest(ChannelHandlerContext ctx, HttpRequest req) throws Exception {
    // Allow only GET methods.
    if (req.getMethod() != GET) {
      sendHttpResponse(ctx, req, new DefaultHttpResponse(HTTP_1_1, FORBIDDEN));
      return;
    }

    // Send the demo page.
    if (req.getUri().equals("/")) {
      HttpResponse res = new DefaultHttpResponse(HTTP_1_1, OK);

      ChannelBuffer content = WebSocketServerIndexPage.getContent(getWebSocketLocation(req));

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

      res.setContent(content);
      sendHttpResponse(ctx, req, res);
      return;
    }

    // Serve the WebSocket handshake request.
    if (req.getUri().equals(WEBSOCKET_PATH)
        && Values.UPGRADE.equalsIgnoreCase(req.getHeader(CONNECTION))
        && WEBSOCKET.equalsIgnoreCase(req.getHeader(Names.UPGRADE))) {

      // Create the WebSocket handshake response.
      HttpResponse res =
          new DefaultHttpResponse(
              HTTP_1_1, new HttpResponseStatus(101, "Web Socket Protocol Handshake"));
      res.addHeader(Names.UPGRADE, WEBSOCKET);
      res.addHeader(CONNECTION, Values.UPGRADE);

      // Fill in the headers and contents depending on handshake method.
      if (req.containsHeader(SEC_WEBSOCKET_KEY1) && req.containsHeader(SEC_WEBSOCKET_KEY2)) {
        // New handshake method with a challenge:
        res.addHeader(SEC_WEBSOCKET_ORIGIN, req.getHeader(ORIGIN));
        res.addHeader(SEC_WEBSOCKET_LOCATION, getWebSocketLocation(req));
        String protocol = req.getHeader(SEC_WEBSOCKET_PROTOCOL);
        if (protocol != null) {
          res.addHeader(SEC_WEBSOCKET_PROTOCOL, protocol);
        }

        // Calculate the answer of the challenge.
        String key1 = req.getHeader(SEC_WEBSOCKET_KEY1);
        String key2 = req.getHeader(SEC_WEBSOCKET_KEY2);
        int a =
            (int)
                (Long.parseLong(key1.replaceAll("[^0-9]", ""))
                    / key1.replaceAll("[^ ]", "").length());
        int b =
            (int)
                (Long.parseLong(key2.replaceAll("[^0-9]", ""))
                    / key2.replaceAll("[^ ]", "").length());
        long c = req.getContent().readLong();
        ChannelBuffer input = ChannelBuffers.buffer(16);
        input.writeInt(a);
        input.writeInt(b);
        input.writeLong(c);
        ChannelBuffer output =
            ChannelBuffers.wrappedBuffer(MessageDigest.getInstance("MD5").digest(input.array()));
        res.setContent(output);
      } else {
        // Old handshake method with no challenge:
        res.addHeader(WEBSOCKET_ORIGIN, req.getHeader(ORIGIN));
        res.addHeader(WEBSOCKET_LOCATION, getWebSocketLocation(req));
        String protocol = req.getHeader(WEBSOCKET_PROTOCOL);
        if (protocol != null) {
          res.addHeader(WEBSOCKET_PROTOCOL, protocol);
        }
      }

      // Upgrade the connection and send the handshake response.
      ChannelPipeline p = ctx.getChannel().getPipeline();
      p.remove("aggregator");
      p.replace("decoder", "wsdecoder", new WebSocketFrameDecoder());

      ctx.getChannel().write(res);

      p.replace("encoder", "wsencoder", new WebSocketFrameEncoder());
      return;
    }

    // Send an error page otherwise.
    sendHttpResponse(ctx, req, new DefaultHttpResponse(HTTP_1_1, FORBIDDEN));
  }
  @Override
  public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
    RequestV2 request = null;
    RendererConfiguration renderer = null;
    String userAgentString = null;
    StringBuilder unknownHeaders = new StringBuilder();
    String separator = "";
    boolean isWindowsMediaPlayer = false;

    HttpRequest nettyRequest = this.nettyRequest = (HttpRequest) e.getMessage();

    InetSocketAddress remoteAddress = (InetSocketAddress) e.getChannel().getRemoteAddress();
    InetAddress ia = remoteAddress.getAddress();

    // Apply the IP filter
    if (filterIp(ia)) {
      e.getChannel().close();
      LOGGER.trace("Access denied for address " + ia + " based on IP filter");
      return;
    }

    LOGGER.trace("Opened request handler on socket " + remoteAddress);
    PMS.get().getRegistry().disableGoToSleep();

    if (HttpMethod.GET.equals(nettyRequest.getMethod())) {
      request = new RequestV2("GET", nettyRequest.getUri().substring(1));
    } else if (HttpMethod.POST.equals(nettyRequest.getMethod())) {
      request = new RequestV2("POST", nettyRequest.getUri().substring(1));
    } else if (HttpMethod.HEAD.equals(nettyRequest.getMethod())) {
      request = new RequestV2("HEAD", nettyRequest.getUri().substring(1));
    } else {
      request =
          new RequestV2(nettyRequest.getMethod().getName(), nettyRequest.getUri().substring(1));
    }

    LOGGER.trace(
        "Request: "
            + nettyRequest.getProtocolVersion().getText()
            + " : "
            + request.getMethod()
            + " : "
            + request.getArgument());

    if (nettyRequest.getProtocolVersion().getMinorVersion() == 0) {
      request.setHttp10(true);
    }

    // The handler makes a couple of attempts to recognize a renderer from its requests.
    // IP address matches from previous requests are preferred, when that fails request
    // header matches are attempted and if those fail as well we're stuck with the
    // default renderer.

    // Attempt 1: try to recognize the renderer by its socket address from previous requests
    renderer = RendererConfiguration.getRendererConfigurationBySocketAddress(ia);

    if (renderer != null) {
      if (!"WMP".equals(renderer.getRendererName())) {
        PMS.get().setRendererfound(renderer);
        request.setMediaRenderer(renderer);
        LOGGER.trace(
            "Matched media renderer \"" + renderer.getRendererName() + "\" based on address " + ia);
      } else {
        LOGGER.trace("Detected and blocked Windows Media Player");
        isWindowsMediaPlayer = true;
      }
    }

    for (String name : nettyRequest.getHeaderNames()) {
      String headerLine = name + ": " + nettyRequest.getHeader(name);
      LOGGER.trace("Received on socket: " + headerLine);

      if (renderer == null
          && headerLine != null
          && headerLine.toUpperCase().startsWith("USER-AGENT")) {
        userAgentString = headerLine.substring(headerLine.indexOf(":") + 1).trim();

        // Attempt 2: try to recognize the renderer by matching the "User-Agent" header
        renderer = RendererConfiguration.getRendererConfigurationByUA(userAgentString);

        if (renderer != null) {
          if (!"WMP".equals(renderer.getRendererName())) {
            request.setMediaRenderer(renderer);
            renderer.associateIP(ia); // Associate IP address for later requests
            PMS.get().setRendererfound(renderer);
            LOGGER.trace(
                "Matched media renderer \""
                    + renderer.getRendererName()
                    + "\" based on header \""
                    + headerLine
                    + "\"");
          } else if (!isWindowsMediaPlayer) {
            LOGGER.trace("Detected and blocked Windows Media Player");
            isWindowsMediaPlayer = true;
          }
        }
      }

      if (renderer == null && headerLine != null) {
        // Attempt 3: try to recognize the renderer by matching an additional header
        renderer = RendererConfiguration.getRendererConfigurationByUAAHH(headerLine);

        if (renderer != null) {
          request.setMediaRenderer(renderer);
          renderer.associateIP(ia); // Associate IP address for later requests
          PMS.get().setRendererfound(renderer);
          LOGGER.trace(
              "Matched media renderer \""
                  + renderer.getRendererName()
                  + "\" based on header \""
                  + headerLine
                  + "\"");
        }
      }

      try {
        StringTokenizer s = new StringTokenizer(headerLine);
        String temp = s.nextToken();
        if (temp.toUpperCase().equals("SOAPACTION:")) {
          request.setSoapaction(s.nextToken());
        } else if (temp.toUpperCase().equals("CALLBACK:")) {
          request.setSoapaction(s.nextToken());
        } else if (headerLine.toUpperCase().indexOf("RANGE: BYTES=") > -1) {
          String nums =
              headerLine.substring(headerLine.toUpperCase().indexOf("RANGE: BYTES=") + 13).trim();
          StringTokenizer st = new StringTokenizer(nums, "-");
          if (!nums.startsWith("-")) {
            request.setLowRange(Long.parseLong(st.nextToken()));
          }
          if (!nums.startsWith("-") && !nums.endsWith("-")) {
            request.setHighRange(Long.parseLong(st.nextToken()));
          } else {
            request.setHighRange(-1);
          }
        } else if (headerLine.toLowerCase().indexOf("transfermode.dlna.org:") > -1) {
          request.setTransferMode(
              headerLine
                  .substring(headerLine.toLowerCase().indexOf("transfermode.dlna.org:") + 22)
                  .trim());
        } else if (headerLine.toLowerCase().indexOf("getcontentfeatures.dlna.org:") > -1) {
          request.setContentFeatures(
              headerLine
                  .substring(headerLine.toLowerCase().indexOf("getcontentfeatures.dlna.org:") + 28)
                  .trim());
        } else {
          Matcher matcher = TIMERANGE_PATTERN.matcher(headerLine);
          if (matcher.find()) {
            String first = matcher.group(1);
            if (first != null) {
              request.setTimeRangeStartString(first);
            }
            String end = matcher.group(2);
            if (end != null) {
              request.setTimeRangeEndString(end);
            }
          } else {
            // If we made it to here, none of the previous header checks matched.
            // Unknown headers make interesting logging info when we cannot recognize
            // the media renderer, so keep track of the truly unknown ones.
            boolean isKnown = false;

            // Try to match possible known headers.
            for (String knownHeaderString : KNOWN_HEADERS) {
              if (headerLine.toLowerCase().startsWith(knownHeaderString.toLowerCase())) {
                isKnown = true;
                break;
              }
            }

            if (!isKnown) {
              // Truly unknown header, therefore interesting. Save for later use.
              unknownHeaders.append(separator).append(headerLine);
              separator = ", ";
            }
          }
        }
      } catch (Exception ee) {
        LOGGER.error("Error parsing HTTP headers", ee);
      }
    }

    if (!isWindowsMediaPlayer) {
      if (request != null) {
        // Still no media renderer recognized?
        if (request.getMediaRenderer() == null) {

          // Attempt 4: Not really an attempt; all other attempts to recognize
          // the renderer have failed. The only option left is to assume the
          // default renderer.
          request.setMediaRenderer(RendererConfiguration.getDefaultConf());
          LOGGER.trace(
              "Using default media renderer: " + request.getMediaRenderer().getRendererName());

          if (userAgentString != null && !userAgentString.equals("FDSSDP")) {
            // We have found an unknown renderer
            LOGGER.info(
                "Media renderer was not recognized. Possible identifying HTTP headers: User-Agent: "
                    + userAgentString
                    + ("".equals(unknownHeaders.toString())
                        ? ""
                        : ", " + unknownHeaders.toString()));
            PMS.get().setRendererfound(request.getMediaRenderer());
          }
        } else {
          if (userAgentString != null) {
            LOGGER.debug("HTTP User-Agent: " + userAgentString);
          }

          LOGGER.trace(
              "Recognized media renderer: " + request.getMediaRenderer().getRendererName());
        }
      }

      if (HttpHeaders.getContentLength(nettyRequest) > 0) {
        byte data[] = new byte[(int) HttpHeaders.getContentLength(nettyRequest)];
        ChannelBuffer content = nettyRequest.getContent();
        content.readBytes(data);
        request.setTextContent(new String(data, "UTF-8"));
      }

      if (request != null) {
        LOGGER.trace(
            "HTTP: "
                + request.getArgument()
                + " / "
                + request.getLowRange()
                + "-"
                + request.getHighRange());
      }

      writeResponse(e, request, ia);
    }
  }
Esempio n. 19
0
  @Override
  public void messageReceived(final ChannelHandlerContext ctx, final MessageEvent e)
      throws Exception {
    Logger.trace("messageReceived: begin");
    final Object msg = e.getMessage();

    // Http request
    if (msg instanceof HttpRequest) {

      final HttpRequest nettyRequest = (HttpRequest) msg;

      // Websocket upgrade
      if (HttpHeaders.Values.UPGRADE.equalsIgnoreCase(nettyRequest.getHeader(CONNECTION))
          && HttpHeaders.Values.WEBSOCKET.equalsIgnoreCase(
              nettyRequest.getHeader(HttpHeaders.Names.UPGRADE))) {
        websocketHandshake(ctx, nettyRequest, e);
        return;
      }

      // Plain old HttpRequest
      try {
        final Request request = parseRequest(ctx, nettyRequest);

        final Response response = new Response();
        Http.Response.current.set(response);

        // Buffered in memory output
        response.out = new ByteArrayOutputStream();

        // Direct output (will be set later)
        response.direct = null;

        // Streamed output (using response.writeChunk)
        response.onWriteChunk(
            new Action<Object>() {

              public void invoke(Object result) {
                writeChunk(request, response, ctx, nettyRequest, result);
              }
            });

        // Raw invocation
        boolean raw = false;
        for (PlayPlugin plugin : Play.plugins) {
          if (plugin.rawInvocation(request, response)) {
            raw = true;
            break;
          }
        }
        if (raw) {
          copyResponse(ctx, request, response, nettyRequest);
        } else {

          // Deleguate to Play framework
          Invoker.invoke(new NettyInvocation(request, response, ctx, nettyRequest, e));
        }

      } catch (Exception ex) {
        serve500(ex, ctx, nettyRequest);
      }
    }

    // Websocket frame
    if (msg instanceof WebSocketFrame) {
      WebSocketFrame frame = (WebSocketFrame) msg;
      websocketFrameReceived(ctx, frame);
    }

    Logger.trace("messageReceived: end");
  }
Esempio n. 20
0
  public Request parseRequest(ChannelHandlerContext ctx, HttpRequest nettyRequest)
      throws Exception {
    Logger.trace("parseRequest: begin");
    Logger.trace("parseRequest: URI = " + nettyRequest.getUri());
    int index = nettyRequest.getUri().indexOf("?");
    String querystring = "";

    String uri = nettyRequest.getUri();
    // Remove domain and port from URI if it's present.
    if (uri.startsWith("http://") || uri.startsWith("https://")) {
      // Begins searching / after 9th character (last / of https://)
      uri = uri.substring(uri.indexOf("/", 9));
    }

    String path = URLDecoder.decode(uri, "UTF-8");
    if (index != -1) {
      path = URLDecoder.decode(uri.substring(0, index), "UTF-8");
      querystring = uri.substring(index + 1);
    }

    final Request request = new Request();

    request.remoteAddress = getRemoteIPAddress(ctx);
    request.method = nettyRequest.getMethod().getName();
    request.path = path;
    request.querystring = querystring;
    final String contentType = nettyRequest.getHeader(CONTENT_TYPE);
    if (contentType != null) {
      request.contentType = contentType.split(";")[0].trim().toLowerCase();
    } else {
      request.contentType = "text/html";
    }

    if (nettyRequest.getHeader("X-HTTP-Method-Override") != null) {
      request.method = nettyRequest.getHeader("X-HTTP-Method-Override").intern();
    }

    ChannelBuffer b = nettyRequest.getContent();
    if (b instanceof FileChannelBuffer) {
      FileChannelBuffer buffer = (FileChannelBuffer) b;
      // An error occurred
      Integer max =
          Integer.valueOf(Play.configuration.getProperty("play.netty.maxContentLength", "-1"));

      request.body = buffer.getInputStream();
      if (!(max == -1 || request.body.available() < max)) {
        request.body = new ByteArrayInputStream(new byte[0]);
      }

    } else {
      ByteArrayOutputStream out = new ByteArrayOutputStream();
      IOUtils.copy(new ChannelBufferInputStream(b), out);
      byte[] n = out.toByteArray();
      request.body = new ByteArrayInputStream(n);
    }

    request.url = uri;
    request.host = nettyRequest.getHeader(HOST);
    request.isLoopback =
        ((InetSocketAddress) ctx.getChannel().getRemoteAddress()).getAddress().isLoopbackAddress()
            && request.host.matches("^127\\.0\\.0\\.1:?[0-9]*$");

    if (request.host == null) {
      request.host = "";
      request.port = 80;
      request.domain = "";
    } else {
      if (request.host.contains(":")) {
        final String[] host = request.host.split(":");
        request.port = Integer.parseInt(host[1]);
        request.domain = host[0];
      } else {
        request.port = 80;
        request.domain = request.host;
      }
    }

    if (Play.configuration.containsKey("XForwardedSupport")
        && nettyRequest.getHeader("X-Forwarded-For") != null) {
      if (!Arrays.asList(
              Play.configuration.getProperty("XForwardedSupport", "127.0.0.1").split(","))
          .contains(request.remoteAddress)) {
        throw new RuntimeException(
            "This proxy request is not authorized: " + request.remoteAddress);
      } else {
        request.secure =
            ("https".equals(Play.configuration.get("XForwardedProto"))
                || "https".equals(nettyRequest.getHeader("X-Forwarded-Proto"))
                || "on".equals(nettyRequest.getHeader("X-Forwarded-Ssl")));
        if (Play.configuration.containsKey("XForwardedHost")) {
          request.host = (String) Play.configuration.get("XForwardedHost");
        } else if (nettyRequest.getHeader("X-Forwarded-Host") != null) {
          request.host = nettyRequest.getHeader("X-Forwarded-Host");
        }
        if (nettyRequest.getHeader("X-Forwarded-For") != null) {
          request.remoteAddress = nettyRequest.getHeader("X-Forwarded-For");
        }
      }
    }

    addToRequest(nettyRequest, request);

    request.resolveFormat();

    request._init();

    Logger.trace("parseRequest: end");
    return request;
  }
Esempio n. 21
0
  private void processRequest(ResponseReceivedEvent event) {

    HttpRequest request = event.getRequest();

    URI uri = null;
    try {
      uri = new URI(request.getUri());
    } catch (URISyntaxException ex) {
      logger.error(
          "Can't create URI from request uri (" + request.getUri() + ")" + ex.getStackTrace());
    }

    events.addElement(request.getMethod() + " | " + request.getUri());
    executedEvents.ensureIndexIsVisible(events.getSize() - 1);

    int id = ++numberOfRequests;
    event.setId(id);

    /* URLs */
    if (urlBase == null) {
      protocol = uri.getScheme();
      host = uri.getHost();
      port = uri.getPort();
      urlBase = protocol + "://" + host;
      urlBaseString = "PROTOCOL + \"://\" + HOST";
      if (port != -1) {
        urlBase += ":" + port;
        urlBaseString += " + \":\" + PORT";
      }
    }

    String requestUrlBase = uri.getScheme() + "://" + uri.getHost();
    if (uri.getPort() != -1) requestUrlBase += ":" + uri.getPort();
    if (requestUrlBase.equals(urlBase)) event.setWithUrlBase(true);
    else urls.put("url_" + id, requestUrlBase + uri.getPath());

    String headerAuthorization = event.getRequest().getHeader("Authorization");
    request.removeHeader("Authorization");
    if (headerAuthorization != null) {
      if (basicAuth == null) {
        // Split on " " and take 2nd group (Basic credentialsInBase64==)
        String credentials =
            new String(Base64.decodeBase64(headerAuthorization.split(" ")[1].getBytes()));
        basicAuth =
            new BasicAuth(requestUrlBase, credentials.split(":")[0], credentials.split(":")[1]);
        event.setBasicAuth(basicAuth);
      } else {
        if (requestUrlBase.equals(basicAuth.getUrlBase())) event.setBasicAuth(basicAuth);
        else basicAuth = null;
      }
    }

    /* Headers */
    Map<String, String> requestHeaders = new TreeMap<String, String>();
    for (Entry<String, String> entry : request.getHeaders())
      requestHeaders.put(entry.getKey(), entry.getValue());
    requestHeaders.remove("Cookie");

    int bestChoice = 0;
    String headerKey = EMPTY;
    MapDifference<String, String> diff;
    Map<String, String> fullHeaders = new TreeMap<String, String>();
    boolean containsHeaders = false;

    if (headers.size() > 0) {
      for (Entry<String, Map<String, String>> header : headers.entrySet()) {

        fullHeaders = new TreeMap<String, String>(header.getValue());
        containsHeaders = false;

        if (header.getValue().containsKey("headers")) {
          fullHeaders.putAll(headers.get(header.getValue().get("headers")));
          fullHeaders.remove("headers");
          containsHeaders = true;
        }

        diff = Maps.difference(fullHeaders, requestHeaders);
        logger.debug(diff.toString());
        if (diff.areEqual()) {
          headerKey = header.getKey();
          bestChoice = 1;
          break;
        } else if (diff.entriesOnlyOnLeft().size() == 0
            && diff.entriesDiffering().size() == 0
            && !containsHeaders) {
          // header are included in requestHeaders
          headerKey = header.getKey();
          bestChoice = 2;
        } else if (bestChoice > 2
            && diff.entriesOnlyOnRight().size() == 0
            && diff.entriesDiffering().size() == 0
            && !containsHeaders) {
          // requestHeaders are included in header
          headerKey = header.getKey();
          bestChoice = 3;
        }
      }
    }

    switch (bestChoice) {
      case 1:
        event.setHeadersId(headerKey);
        break;
      case 2:
        diff = Maps.difference(headers.get(headerKey), requestHeaders);
        TreeMap<String, String> tm2 = new TreeMap<String, String>(diff.entriesOnlyOnRight());
        headers.put("headers_" + id, tm2);
        headers.get("headers_" + id).put("headers", headerKey);
        event.setHeadersId("headers_" + id);
        break;
      case 3:
        diff = Maps.difference(headers.get(headerKey), requestHeaders);
        TreeMap<String, String> tm3 = new TreeMap<String, String>(diff.entriesInCommon());
        headers.put("headers_" + id, tm3);
        event.setHeadersId("headers_" + id);
        headers.remove(headerKey);
        tm3 = new TreeMap<String, String>(diff.entriesOnlyOnLeft());
        headers.put(headerKey, tm3);
        headers.get(headerKey).put("headers", "headers_" + id);
        break;
      default:
        headers.put("headers_" + id, requestHeaders);
        event.setHeadersId("headers_" + id);
    }

    /* Add check if status is not in 20X */
    if ((event.getResponse().getStatus().getCode() < 200)
        || (event.getResponse().getStatus().getCode() > 210)) event.setWithCheck(true);

    /* Params */
    QueryStringDecoder decoder = new QueryStringDecoder(request.getUri());
    event.getRequestParams().putAll((decoder.getParameters()));

    /* Content */
    if (request.getContent().capacity() > 0) {
      String content = new String(request.getContent().array());
      // We check if it's a form validation and so we extract post params
      if ("application/x-www-form-urlencoded".equals(request.getHeader("Content-Type"))) {
        decoder = new QueryStringDecoder("http://localhost/?" + content);
        event.getRequestParams().putAll(decoder.getParameters());
      } else {
        event.setWithBody(true);
        dumpRequestBody(id, content);
      }
    }

    listEvents.add(event);
  }
  @Override
  public void handle(ChannelHandlerContext ctx, HttpRequest request) {

    Tracker.getInstance().track(request);

    final String tenantId = request.getHeader("tenantId");

    if (!(request instanceof HTTPRequestWithDecodedQueryParams)) {
      sendResponse(
          ctx, request, "Missing query params: from, to, points", HttpResponseStatus.BAD_REQUEST);
      return;
    }

    final String body = request.getContent().toString(Constants.DEFAULT_CHARSET);

    if (body == null || body.isEmpty()) {
      sendResponse(
          ctx,
          request,
          "Invalid body. Expected JSON array of metrics.",
          HttpResponseStatus.BAD_REQUEST);
      return;
    }

    List<String> locators = new ArrayList<String>();
    try {
      locators.addAll(getLocatorsFromJSONBody(tenantId, body));
    } catch (Exception ex) {
      log.debug(ex.getMessage(), ex);
      sendResponse(ctx, request, ex.getMessage(), HttpResponseStatus.BAD_REQUEST);
      return;
    }

    if (locators.size() > maxMetricsPerRequest) {
      sendResponse(
          ctx,
          request,
          "Too many metrics fetch in a single call. Max limit is " + maxMetricsPerRequest + ".",
          HttpResponseStatus.BAD_REQUEST);
      return;
    }

    HTTPRequestWithDecodedQueryParams requestWithParams =
        (HTTPRequestWithDecodedQueryParams) request;
    final Timer.Context httpBatchMetricsFetchTimerContext = httpBatchMetricsFetchTimer.time();
    try {
      RollupsQueryParams params = PlotRequestParser.parseParams(requestWithParams.getQueryParams());
      Map<Locator, MetricData> results =
          getRollupByGranularity(
              tenantId,
              locators,
              params.getRange().getStart(),
              params.getRange().getStop(),
              params.getGranularity(tenantId));
      JSONObject metrics = serializer.transformRollupData(results, params.getStats());
      final JsonElement element = parser.parse(metrics.toString());
      final String jsonStringRep = gson.toJson(element);
      sendResponse(ctx, request, jsonStringRep, HttpResponseStatus.OK);
    } catch (InvalidRequestException e) {
      log.debug(e.getMessage());
      sendResponse(ctx, request, e.getMessage(), HttpResponseStatus.BAD_REQUEST);
    } catch (SerializationException e) {
      log.debug(e.getMessage(), e);
      sendResponse(ctx, request, e.getMessage(), HttpResponseStatus.INTERNAL_SERVER_ERROR);
    } catch (Exception e) {
      log.error(e.getMessage(), e);
      sendResponse(ctx, request, e.getMessage(), HttpResponseStatus.INTERNAL_SERVER_ERROR);
    } finally {
      httpBatchMetricsFetchTimerContext.stop();
    }
  }