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