예제 #1
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, "");
    }
  }
예제 #2
0
  private void executeBatchQueries(HttpRequest request, HttpResponder responder) {
    if (HttpHeaders.getContentLength(request) > 0) {
      try {
        String json = request.getContent().toString(Charsets.UTF_8);
        Map<String, QueryRequestFormat> queries =
            GSON.fromJson(json, new TypeToken<Map<String, QueryRequestFormat>>() {}.getType());

        LOG.trace("Received Queries {}", queries);

        Map<String, MetricQueryResult> queryFinalResponse = Maps.newHashMap();
        for (Map.Entry<String, QueryRequestFormat> query : queries.entrySet()) {
          MetricQueryRequest queryRequest = getQueryRequestFromFormat(query.getValue());
          queryFinalResponse.put(query.getKey(), executeQuery(queryRequest));
        }
        responder.sendJson(HttpResponseStatus.OK, queryFinalResponse);
      } catch (IllegalArgumentException e) {
        LOG.warn("Invalid request", e);
        responder.sendString(HttpResponseStatus.BAD_REQUEST, e.getMessage());
      } catch (Exception e) {
        LOG.error("Exception querying metrics ", e);
        responder.sendString(
            HttpResponseStatus.INTERNAL_SERVER_ERROR, "Internal error while querying for metrics");
      }
    } else {
      responder.sendJson(HttpResponseStatus.BAD_REQUEST, "Batch request with empty content");
    }
  }
예제 #3
0
  @Override
  public void messageReceived(final ChannelHandlerContext ctx, final MessageEvent e)
      throws Exception {

    if (!chunked) {
      final HttpRequest request = (HttpRequest) e.getMessage();

      final ChannelBuffer buffer = request.getContent();
      receivedData.write(buffer.array());
      // System.out.println("received "+buffer.array() );
      // System.out.println(buffer.array().length);
      if (!request.isChunked()) {
        processRequest(e);
      } else {
        chunked = true;
      }
      // final boolean keepAlive = isKeepAlive(request);
    } else {
      final HttpChunk chunk = (HttpChunk) e.getMessage();
      final ChannelBuffer buffer = chunk.getContent();
      receivedData.write(buffer.array());
      if (chunk.isLast()) {
        processRequest(e);
      }
    }
  }
예제 #4
0
 @Path("/queue")
 @POST
 public void getPing(HttpRequest request, HttpResponder responder) {
   String dataPacket = request.getContent().toString(Charsets.UTF_8);
   LOG.info("/ping Got Data {}", dataPacket);
   queue.add(dataPacket);
   latch.countDown();
   responder.sendStatus(HttpResponseStatus.OK);
 }
예제 #5
0
파일: HttpQuery.java 프로젝트: gitbrid/tsdb
 private String getUri() {
   String uri = null;
   if (HttpMethod.POST == request.getMethod()) {
     uri = request.getUri() + "?" + request.getContent().toString("ISO-8859-1");
   } else {
     uri = request.getUri();
   }
   return uri;
 }
예제 #6
0
 /*
  *  获取POST请求中的请求参数
  * @param           [req]           一个POST请求
  */
 static HashMap<String, String> getPostParameter(HttpRequest req) {
   HashMap<String, String> postParameterList = new HashMap<String, String>();
   ChannelBuffer buf = req.getContent();
   for (String parameterEquation : buf.toString(CharsetUtil.UTF_8).split("&")) {
     String[] parameterList = parameterEquation.split("=");
     postParameterList.put(parameterList[0], parameterList[1]);
   }
   return postParameterList;
 }
예제 #7
0
  private HttpRequest rewriteRequest(HttpRequest request, boolean isStreaming) {
    if (!isStreaming) {
      return request;
    }

    if (!request.isChunked() || request.getContent().readable()) {
      request.setChunked(true);
      request.setContent(ChannelBuffers.EMPTY_BUFFER);
    }
    return request;
  }
  @Override
  public Message toCamelMessage(
      HttpRequest request, Exchange exchange, NettyHttpConfiguration configuration)
      throws Exception {
    LOG.trace("toCamelMessage: {}", request);

    NettyHttpMessage answer = new NettyHttpMessage(request, null);
    answer.setExchange(exchange);
    if (configuration.isMapHeaders()) {
      populateCamelHeaders(request, answer.getHeaders(), exchange, configuration);
    }

    if (configuration.isDisableStreamCache()) {
      // keep the body as is, and use type converters
      answer.setBody(request.getContent());
    } else {
      // turn the body into stream cached
      NettyChannelBufferStreamCache cache = new NettyChannelBufferStreamCache(request.getContent());
      answer.setBody(cache);
    }
    return answer;
  }
  /**
   * Interface method implementation. Reads and processes Http commands sent to the service proxy.
   * Expects data in the Http protocol.
   *
   * @see
   *     org.jboss.netty.channel.SimpleChannelUpstreamHandler#handleUpstream(org.jboss.netty.channel.ChannelHandlerContext,
   *     org.jboss.netty.channel.ChannelEvent)
   */
  public void messageReceived(ChannelHandlerContext ctx, MessageEvent messageEvent)
      throws Exception {

    HttpRequest request = (HttpRequest) messageEvent.getMessage();
    LOGGER.debug("Request is: " + request.getMethod() + " " + request.getUri());

    this.processRequestHeaders(request);

    ChannelBuffer inputBuffer = request.getContent();
    byte[] requestData = new byte[inputBuffer.readableBytes()];
    inputBuffer.readBytes(requestData, 0, requestData.length);

    // Prepare request Wrapper
    HttpRequestWrapper executorHttpRequest = new HttpRequestWrapper();
    executorHttpRequest.setData(requestData);
    executorHttpRequest.setMethod(request.getMethod().toString());
    executorHttpRequest.setUri(request.getUri());
    executorHttpRequest.setHeaders(request.getHeaders());
    executorHttpRequest.setProtocol(request.getProtocolVersion().getProtocolName());
    executorHttpRequest.setMajorVersion(request.getProtocolVersion().getMajorVersion());
    executorHttpRequest.setMinorVersion(request.getProtocolVersion().getMinorVersion());

    // executor
    String proxy = this.proxyMap.get(this.getRoutingKey(request));
    if (proxy == null) {
      proxy = this.proxyMap.get(RoutingHttpChannelHandler.ALL_ROUTES);
      LOGGER.info(
          "Routing key for : " + request.getUri() + " returned null. Using default proxy instead.");
    }
    Executor executor = this.repository.getExecutor(proxy, proxy, executorHttpRequest);

    // execute
    HttpResponse response = null;
    try {
      response = (HttpResponse) executor.execute();
    } catch (Exception e) {
      throw new RuntimeException(
          "Error in executing HTTP request:" + proxy + " URI:" + request.getUri(), e);
    } finally {

      // Publishes event both in case of success and failure.
      Class eventSource = (executor == null) ? this.getClass() : executor.getClass();
      if (eventProducer != null)
        eventProducer.publishEvent(executor, request.getUri(), eventSource, HTTP_HANDLER);
      else LOGGER.debug("eventProducer not set, not publishing event");
    }

    // send response
    writeCommandExecutionResponse(ctx, messageEvent, response);
  }
예제 #10
0
  HttpMethodInfo(
      Method method,
      HttpHandler handler,
      HttpRequest request,
      HttpResponder responder,
      Object[] args) {
    this.method = method;
    this.handler = handler;
    this.isChunkedRequest = request.isChunked();
    this.requestContent = request.getContent();
    this.responder = responder;
    this.isStreaming = BodyConsumer.class.isAssignableFrom(method.getReturnType());

    // The actual arguments list to invoke handler method
    this.args = new Object[args.length + 2];
    this.args[0] = rewriteRequest(request, isStreaming);
    this.args[1] = responder;
    System.arraycopy(args, 0, this.args, 2, args.length);
  }
예제 #11
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;
  }
 public static String myTransformer(HttpRequest request) {
   String in = request.getContent().toString(Charset.forName("UTF-8"));
   return "Bye " + in;
 }
예제 #13
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 messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
    RequestV2 request = null;
    RendererConfiguration renderer = null;
    String userAgentString = null;
    StringBuilder unknownHeaders = new StringBuilder();
    String separator = "";

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

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

    // Is the request from our own Cling service, i.e. self-originating?
    boolean isSelf =
        ia.getHostAddress().equals(PMS.get().getServer().getHost())
            && nettyRequest.headers().get(HttpHeaders.Names.USER_AGENT) != null
            && nettyRequest.headers().get(HttpHeaders.Names.USER_AGENT).contains("UMS/");

    // Filter if required
    if (isSelf || filterIp(ia)) {
      e.getChannel().close();
      LOGGER.trace(
          isSelf
              ? ("Ignoring self-originating request from " + ia + ":" + remoteAddress.getPort())
              : ("Access denied for address " + ia + " based on IP filter"));
      return;
    }

    LOGGER.trace("Opened request handler on socket " + remoteAddress);
    PMS.get().getRegistry().disableGoToSleep();
    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);
    }

    HttpHeaders headers = nettyRequest.headers();

    // 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 the renderer exists but isn't marked as loaded it means it's unrecognized
    // by upnp and we still need to attempt http recognition here.
    if (renderer == null || !renderer.loaded) {
      // Attempt 2: try to recognize the renderer by matching headers
      renderer = RendererConfiguration.getRendererConfigurationByHeaders(headers.entries(), ia);
    }

    if (renderer != null) {
      request.setMediaRenderer(renderer);
    }

    Set<String> headerNames = headers.names();
    Iterator<String> iterator = headerNames.iterator();
    while (iterator.hasNext()) {
      String name = iterator.next();
      String headerLine = name + ": " + headers.get(name);
      LOGGER.trace("Received on socket: " + headerLine);

      if (headerLine.toUpperCase().startsWith("USER-AGENT")) {
        userAgentString = headerLine.substring(headerLine.indexOf(':') + 1).trim();
      }

      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().contains("RANGE: BYTES=")) {
          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().contains("transfermode.dlna.org:")) {
          request.setTransferMode(
              headerLine
                  .substring(headerLine.toLowerCase().indexOf("transfermode.dlna.org:") + 22)
                  .trim());
        } else if (headerLine.toLowerCase().contains("getcontentfeatures.dlna.org:")) {
          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 known headers.
            String lowerCaseHeaderLine = headerLine.toLowerCase();
            for (String knownHeaderString : KNOWN_HEADERS) {
              if (lowerCaseHeaderLine.startsWith(knownHeaderString)) {
                isKnown = true;
                break;
              }
            }

            // It may be unusual but already known
            if (renderer != null) {
              String additionalHeader = renderer.getUserAgentAdditionalHttpHeader();
              if (StringUtils.isNotBlank(additionalHeader)
                  && lowerCaseHeaderLine.startsWith(additionalHeader)) {
                isKnown = true;
              }
            }

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

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

      // Attempt 3: 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.resolve(ia, null));
      if (request.getMediaRenderer() != null) {
        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 RendererConfiguration.resolve() didn't return the default renderer
        // it means we know via upnp that it's not really a renderer.
        return;
      }
    } else {
      if (userAgentString != null) {
        LOGGER.debug("HTTP User-Agent: " + userAgentString);
      }

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

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

    LOGGER.trace(
        "HTTP: "
            + request.getArgument()
            + " / "
            + request.getLowRange()
            + "-"
            + request.getHighRange());

    writeResponse(ctx, e, request, ia);
  }
예제 #15
0
  @Override
  public void populateCamelHeaders(
      HttpRequest request,
      Map<String, Object> headers,
      Exchange exchange,
      NettyHttpConfiguration configuration)
      throws Exception {
    LOG.trace("populateCamelHeaders: {}", request);

    // NOTE: these headers is applied using the same logic as camel-http/camel-jetty to be
    // consistent

    headers.put(Exchange.HTTP_METHOD, request.getMethod().getName());
    // strip query parameters from the uri
    String s = request.getUri();
    if (s.contains("?")) {
      s = ObjectHelper.before(s, "?");
    }

    // we want the full path for the url, as the client may provide the url in the HTTP headers as
    // absolute or relative, eg
    //   /foo
    //   http://servername/foo
    String http = configuration.isSsl() ? "https://" : "http://";
    if (!s.startsWith(http)) {
      if (configuration.getPort() != 80) {
        s = http + configuration.getHost() + ":" + configuration.getPort() + s;
      } else {
        s = http + configuration.getHost() + s;
      }
    }

    headers.put(Exchange.HTTP_URL, s);
    // uri is without the host and port
    URI uri = new URI(request.getUri());
    // uri is path and query parameters
    headers.put(Exchange.HTTP_URI, uri.getPath());
    headers.put(Exchange.HTTP_QUERY, uri.getQuery());
    headers.put(Exchange.HTTP_RAW_QUERY, uri.getRawQuery());

    // strip the starting endpoint path so the path is relative to the endpoint uri
    String path = uri.getPath();
    if (configuration.getPath() != null && path.startsWith(configuration.getPath())) {
      path = path.substring(configuration.getPath().length());
    }
    headers.put(Exchange.HTTP_PATH, path);

    if (LOG.isTraceEnabled()) {
      LOG.trace("HTTP-Method {}", request.getMethod().getName());
      LOG.trace("HTTP-Uri {}", request.getUri());
    }

    for (String name : request.headers().names()) {
      // mapping the content-type
      if (name.toLowerCase(Locale.US).equals("content-type")) {
        name = Exchange.CONTENT_TYPE;
      }

      if (name.toLowerCase(Locale.US).equals("authorization")) {
        String value = request.headers().get(name);
        // store a special header that this request was authenticated using HTTP Basic
        if (value != null && value.trim().startsWith("Basic")) {
          if (headerFilterStrategy != null
              && !headerFilterStrategy.applyFilterToExternalHeaders(
                  NettyHttpConstants.HTTP_AUTHENTICATION, "Basic", exchange)) {
            NettyHttpHelper.appendHeader(headers, NettyHttpConstants.HTTP_AUTHENTICATION, "Basic");
          }
        }
      }

      // add the headers one by one, and use the header filter strategy
      List<String> values = request.headers().getAll(name);
      Iterator<?> it = ObjectHelper.createIterator(values);
      while (it.hasNext()) {
        Object extracted = it.next();
        Object decoded = shouldUrlDecodeHeader(configuration, name, extracted, "UTF-8");
        LOG.trace("HTTP-header: {}", extracted);
        if (headerFilterStrategy != null
            && !headerFilterStrategy.applyFilterToExternalHeaders(name, decoded, exchange)) {
          NettyHttpHelper.appendHeader(headers, name, decoded);
        }
      }
    }

    // add uri parameters as headers to the Camel message
    if (request.getUri().contains("?")) {
      String query = ObjectHelper.after(request.getUri(), "?");
      Map<String, Object> uriParameters = URISupport.parseQuery(query, false, true);

      for (Map.Entry<String, Object> entry : uriParameters.entrySet()) {
        String name = entry.getKey();
        Object values = entry.getValue();
        Iterator<?> it = ObjectHelper.createIterator(values);
        while (it.hasNext()) {
          Object extracted = it.next();
          Object decoded = shouldUrlDecodeHeader(configuration, name, extracted, "UTF-8");
          LOG.trace("URI-Parameter: {}", extracted);
          if (headerFilterStrategy != null
              && !headerFilterStrategy.applyFilterToExternalHeaders(name, decoded, exchange)) {
            NettyHttpHelper.appendHeader(headers, name, decoded);
          }
        }
      }
    }

    // if body is application/x-www-form-urlencoded then extract the body as query string and append
    // as headers
    // if it is a bridgeEndpoint we need to skip this part of work
    if (request.getMethod().getName().equals("POST")
        && request.headers().get(Exchange.CONTENT_TYPE) != null
        && request
            .headers()
            .get(Exchange.CONTENT_TYPE)
            .startsWith(NettyHttpConstants.CONTENT_TYPE_WWW_FORM_URLENCODED)
        && !configuration.isBridgeEndpoint()) {

      String charset = "UTF-8";

      // Push POST form params into the headers to retain compatibility with DefaultHttpBinding
      String body = request.getContent().toString(Charset.forName(charset));
      if (ObjectHelper.isNotEmpty(body)) {
        for (String param : body.split("&")) {
          String[] pair = param.split("=", 2);
          if (pair.length == 2) {
            String name = shouldUrlDecodeHeader(configuration, "", pair[0], charset);
            String value = shouldUrlDecodeHeader(configuration, name, pair[1], charset);
            if (headerFilterStrategy != null
                && !headerFilterStrategy.applyFilterToExternalHeaders(name, value, exchange)) {
              NettyHttpHelper.appendHeader(headers, name, value);
            }
          } else {
            throw new IllegalArgumentException(
                "Invalid parameter, expected to be a pair but was " + param);
          }
        }
      }
    }
  }
  @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);
    }
  }
예제 #17
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));
  }
예제 #18
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;
  }
  @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();
    }
  }
예제 #20
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 {
    if (!(e.getMessage() instanceof HttpRequest)) {
      super.messageReceived(ctx, e);
    }

    HttpRequest request = (HttpRequest) e.getMessage();
    URI uri = entityManager.normalizeURI(getEntityManager().getURIBase() + request.getUri());
    String path = uri.getPath();

    System.out.println("# received request: " + uri);

    /*
     * TODO:
     * - if GET "$base/entities/create", return entity creation form
     * - if GET "$base/entities/" || GET "$base/.well-known/servers" return entity list
     * - if POST "$base/entities/", call createEntity($postdata)
     *
     * - if GET "$base/sources/", return sources list
     * - if GET "$base/sources/edit" return sources edit form
     * - if POST "$base/sources/", call setSources($postdata)
     */

    if (uri.equals(entityManager.normalizeURI(pathPrefix + "/list-entities"))) {
      if (request.getMethod() == HttpMethod.GET) {
        StringBuffer sb = new StringBuffer();
        sb.append("<html><head><title>SLSE List</title></head><body><h1>SLSE List</h1><ol>");

        for (ServiceLevelSemanticEntity slse : this.slseCache.getAll()) {
          sb.append("<li>");
          sb.append(slse.getURI() + "<pre>" + slse.getDescribes() + "</pre>");
          sb.append("</li>");
        }

        sb.append("</ol></body></html>");

        Channels.write(ctx.getChannel(), Answer.create(sb.toString()));
      }
    } else if (uri.equals(entityManager.normalizeURI(pathPrefix + "/create-entity"))) {
      if (request.getMethod() == HttpMethod.GET) {
        // copy into
        // HttpResponse response = new DefaultHttpResponse(request.getProtocolVersion(),
        // HttpResponseStatus.OK);
        // response.setContent(ChannelBuffers.wrappedBuffer(htmlContent));
        Channels.write(ctx.getChannel(), Answer.create(new String(htmlContent)));
        //				Channels.write(ctx.getChannel(),
        //						Answer.create(new File("data/slse/ui/create_entity_form.html")));
      } else if (request.getMethod() == HttpMethod.POST) {
        QueryStringDecoder qsd =
            new QueryStringDecoder(
                "http://blub.blah/?" + request.getContent().toString(Charset.defaultCharset()));

        String elementsQuery = "";
        String name = "";
        boolean dependsOnSensorValues = false;
        boolean multiNodeQuery = false;

        for (Map.Entry<String, List<String>> entry : qsd.getParameters().entrySet()) {
          String key = entry.getKey();
          for (String value : entry.getValue()) {
            if (entry.getKey().equals("elementsQuery")) {
              elementsQuery = value;
            } else if (entry.getKey().equals("name")) {
              name = value;
            } else if (key.equals("dependsOnSensorValues") && value.equals("yes")) {
              dependsOnSensorValues = true;
            } else if (key.equals("multiNodeQuery") && value.equals("yes")) {
              multiNodeQuery = true;
            }
          }
        }

        System.out.println(
            "# adding rule: name="
                + name
                + " dependsOnSensorValues="
                + dependsOnSensorValues
                + " multiNodeQuery="
                + multiNodeQuery);

        slseBuilder.addRule(name, elementsQuery, dependsOnSensorValues, multiNodeQuery);

        Channels.write(
            ctx.getChannel(),
            Answer.create(
                "<html><head><meta http-equiv=\"REFRESH\" content=\"0;url=/\"></head></html>"));
      }
    } else {
      uri = entityManager.toThing(uri);
      Model r = ModelFactory.createDefaultModel();

      if (waitForPolling) {
        //    System.out.println("# waiting for esecache: " + uri);
        synchronized (eseCache) {
          while (!eseCache.isPollComplete()) {
            try {
              eseCache.wait(1000);
            } catch (InterruptedException ex) {
              ex
                  .printStackTrace(); // To change body of catch statement use File | Settings |
                                      // File Templates.
            }
          }
        }
      }

      //  System.out.println("# waiting for slseCache: " + uri);
      synchronized (slseCache) {
        if (slseCache.get(uri.toString()) == null) {
          System.out.println(
              "! SLSE not found in cache: " + uri.toString() + " returning empty model");
        } else {
          r.add(slseCache.get(uri.toString()).getModel());
        }
      }
      ChannelFuture future = Channels.write(ctx.getChannel(), r);
      if (!HttpHeaders.isKeepAlive(request)) {
        future.addListener(ChannelFutureListener.CLOSE);
      }
      // System.out.println("# done: " + uri);

    }
  }
예제 #22
0
  @Override
  protected void httpMessageReceived(
      ChannelHandlerContext ctx, MessageEvent e, HttpRequest httpRequest) throws Exception {

    HttpVersion version = httpRequest.getProtocolVersion();
    URI httpLocation = getEffectiveURI(httpRequest);
    if (httpLocation == null) {
      // see RFC-7230 section 5.4 Host
      HttpResponse httpResponse = new DefaultHttpResponse(version, BAD_REQUEST);
      ChannelFuture future = future(ctx.getChannel());
      write(ctx, future, httpResponse);
      return;
    }

    // channel's local address is resolved address so get the bind address from
    // server channel's attachment
    ChannelAddress transportCandidate =
        (ChannelAddress) ctx.getChannel().getParent().getAttachment();
    ChannelAddress candidate = new ChannelAddress(httpLocation, transportCandidate);

    Entry<ChannelAddress, HttpServerChannel> httpBinding = httpBindings.floorEntry(candidate);

    if (httpBinding == null) {
      HttpResponse httpResponse = new DefaultHttpResponse(version, NOT_FOUND);
      ChannelFuture future = future(ctx.getChannel());
      write(ctx, future, httpResponse);
      return;
    }

    HttpServerChannel parent = httpBinding.getValue();
    ChannelFactory factory = parent.getFactory();
    ChannelConfig config = parent.getConfig();
    ChannelPipelineFactory pipelineFactory = config.getPipelineFactory();
    ChannelPipeline pipeline = pipelineFactory.getPipeline();
    ChannelAddress httpLocalAddress = parent.getLocalAddress();

    Channel transport = ctx.getChannel();
    ChannelAddress remoteAddress = remoteAddress(transport);
    ChannelAddress httpRemoteAddress = new ChannelAddress(httpLocation, remoteAddress, true);

    HttpChildChannelSink sink = new HttpChildChannelSink(transport);
    HttpChildChannel httpChildChannel = new HttpChildChannel(parent, factory, pipeline, sink);
    HttpChannelConfig httpChildConfig = httpChildChannel.getConfig();
    httpChildConfig.setMethod(httpRequest.getMethod());
    httpChildConfig.setVersion(version);
    httpChildConfig.getReadHeaders().set(httpRequest.headers());
    httpChildConfig.setReadQuery(new QueryStringDecoder(httpRequest.getUri()));
    httpChildConfig.setWriteQuery(new QueryStringEncoder(httpRequest.getUri()));
    httpChildConfig.setStatus(HttpResponseStatus.OK);

    this.httpChildChannel = httpChildChannel;

    ChannelBuffer content = httpRequest.getContent();

    // update read state before firing channel events
    if (isTransferEncodingChunked(httpRequest)) {
      httpChildChannel.readState(HttpReadState.CONTENT_CHUNKED);
    } else if (isContentLengthSet(httpRequest)) {
      long contentLength = getContentLength(httpRequest);
      contentLength -= content.readableBytes();
      if (contentLength > 0) {
        httpChildChannel.readState(HttpReadState.CONTENT_CHUNKED);
      } else {
        httpChildChannel.readState(HttpReadState.CONTENT_COMPLETE);
      }
    } else {
      // see RFC-7230 section 3.3
      // content indicated by presence of Content-Length or Transfer-Encoding
      httpChildChannel.readState(HttpReadState.CONTENT_COMPLETE);
    }

    fireChannelOpen(httpChildChannel);

    httpChildChannel.setLocalAddress(httpLocalAddress);
    httpChildChannel.setBound();
    fireChannelBound(httpChildChannel, httpLocalAddress);

    httpChildChannel.setRemoteAddress(httpRemoteAddress);
    httpChildChannel.setConnected();
    fireChannelConnected(httpChildChannel, httpRemoteAddress);

    if (content.readable()) {
      fireMessageReceived(httpChildChannel, content);
    }

    // note: status may be set in reaction to one of the above events, such as CONNECTED
    //       so defer status code check until this point
    if (httpChildConfig.getStatus().getCode() == SWITCHING_PROTOCOLS.getCode()) {
      httpChildChannel.readState(HttpReadState.UPGRADED);
    }

    switch (httpChildChannel.readState()) {
      case CONTENT_COMPLETE:
        fireInputShutdown(httpChildChannel);
        this.httpChildChannel = null;
        if (httpChildChannel.setReadClosed()) {
          fireChannelDisconnected(httpChildChannel);
          fireChannelUnbound(httpChildChannel);
          fireChannelClosed(httpChildChannel);
        }
        break;
      default:
        break;
    }
  }