Esempio n. 1
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);
        }
      }
    }
  }
  @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;
  }
  /**
   * 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);
  }
Esempio n. 4
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);
  }
 /**
  * Finalize the request by preparing the Header in the request and returns the request ready to be
  * sent.<br>
  * Once finalized, no data must be added.<br>
  * If the request does not need chunk (isChunked() == false), this request is the only object to
  * send to the remote server.
  *
  * @return the request object (chunked or not according to size of body)
  * @throws ErrorDataEncoderException if the encoding is in error or if the finalize were already
  *     done
  */
 public HttpRequest finalizeRequest() throws ErrorDataEncoderException {
   // Finalize the multipartHttpDatas
   if (!headerFinalized) {
     if (isMultipart) {
       InternalAttribute internal = new InternalAttribute();
       if (duringMixedMode) {
         internal.addValue("\r\n--" + multipartMixedBoundary + "--");
       }
       internal.addValue("\r\n--" + multipartDataBoundary + "--\r\n");
       multipartHttpDatas.add(internal);
       multipartMixedBoundary = null;
       currentFileUpload = null;
       duringMixedMode = false;
       globalBodySize += internal.size();
     }
     headerFinalized = true;
   } else {
     throw new ErrorDataEncoderException("Header already encoded");
   }
   List<String> contentTypes = request.getHeaders(HttpHeaders.Names.CONTENT_TYPE);
   List<String> transferEncoding = request.getHeaders(HttpHeaders.Names.TRANSFER_ENCODING);
   if (contentTypes != null) {
     request.removeHeader(HttpHeaders.Names.CONTENT_TYPE);
     for (String contentType : contentTypes) {
       // "multipart/form-data; boundary=--89421926422648"
       if (contentType.toLowerCase().startsWith(HttpHeaders.Values.MULTIPART_FORM_DATA)) {
         // ignore
       } else if (contentType
           .toLowerCase()
           .startsWith(HttpHeaders.Values.APPLICATION_X_WWW_FORM_URLENCODED)) {
         // ignore
       } else {
         request.addHeader(HttpHeaders.Names.CONTENT_TYPE, contentType);
       }
     }
   }
   if (isMultipart) {
     String value =
         HttpHeaders.Values.MULTIPART_FORM_DATA
             + "; "
             + HttpHeaders.Values.BOUNDARY
             + "="
             + multipartDataBoundary;
     request.addHeader(HttpHeaders.Names.CONTENT_TYPE, value);
   } else {
     // Not multipart
     request.addHeader(
         HttpHeaders.Names.CONTENT_TYPE, HttpHeaders.Values.APPLICATION_X_WWW_FORM_URLENCODED);
   }
   // Now consider size for chunk or not
   long realSize = globalBodySize;
   if (isMultipart) {
     iterator = multipartHttpDatas.listIterator();
   } else {
     realSize -= 1; // last '&' removed
     iterator = multipartHttpDatas.listIterator();
   }
   request.setHeader(HttpHeaders.Names.CONTENT_LENGTH, String.valueOf(realSize));
   if (realSize > HttpPostBodyUtil.chunkSize) {
     isChunked = true;
     if (transferEncoding != null) {
       request.removeHeader(HttpHeaders.Names.TRANSFER_ENCODING);
       for (String v : transferEncoding) {
         if (v.equalsIgnoreCase(HttpHeaders.Values.CHUNKED)) {
           // ignore
         } else {
           request.addHeader(HttpHeaders.Names.TRANSFER_ENCODING, v);
         }
       }
     }
     request.addHeader(HttpHeaders.Names.TRANSFER_ENCODING, HttpHeaders.Values.CHUNKED);
     request.setContent(ChannelBuffers.EMPTY_BUFFER);
   } else {
     // get the only one body and set it to the request
     HttpChunk chunk = nextChunk();
     request.setContent(chunk.getContent());
   }
   return request;
 }