Search in sources :

Example 16 with IndividualRequest

use of com.linkedin.restli.common.multiplexer.IndividualRequest in project rest.li by linkedin.

the class TestMultiplexedRequestHandlerImpl method testHandleSequentialRequests.

@Test(dataProvider = "multiplexerConfigurations")
public void testHandleSequentialRequests(MultiplexerRunMode multiplexerRunMode) throws Exception {
    SynchronousRequestHandler mockHandler = createMockHandler();
    MultiplexedRequestHandlerImpl multiplexer = createMultiplexer(mockHandler, multiplexerRunMode);
    RequestContext requestContext = new RequestContext();
    IndividualRequest indRequest1 = fakeIndRequest(BAR_URL);
    IndividualRequest indRequest0 = fakeIndRequest(FOO_URL, ImmutableMap.of("1", indRequest1));
    RestRequest request = fakeMuxRestRequest(ImmutableMap.of("0", indRequest0));
    // set expectations
    expect(mockHandler.handleRequestSync(fakeIndRestRequest(FOO_URL), requestContext)).andReturn(fakeIndRestResponse(FOO_ENTITY));
    expect(mockHandler.handleRequestSync(fakeIndRestRequest(BAR_URL), requestContext)).andReturn(fakeIndRestResponse(BAR_ENTITY));
    // switch into replay mode
    replay(mockHandler);
    FutureCallback<RestResponse> callback = new FutureCallback<>();
    multiplexer.handleRequest(request, requestContext, callback);
    RestResponse muxRestResponse = callback.get();
    RestResponse expectedMuxRestResponse = fakeMuxRestResponse(ImmutableMap.of(0, fakeIndResponse(FOO_JSON_BODY), 1, fakeIndResponse(BAR_JSON_BODY)));
    assertEquals(muxRestResponse, expectedMuxRestResponse);
    verify(mockHandler);
}
Also used : IndividualRequest(com.linkedin.restli.common.multiplexer.IndividualRequest) RestRequest(com.linkedin.r2.message.rest.RestRequest) RestResponse(com.linkedin.r2.message.rest.RestResponse) RequestContext(com.linkedin.r2.message.RequestContext) FutureCallback(com.linkedin.common.callback.FutureCallback) Test(org.testng.annotations.Test)

Example 17 with IndividualRequest

use of com.linkedin.restli.common.multiplexer.IndividualRequest in project rest.li by linkedin.

the class TestMultiplexedRequestHandlerImpl method fakeIndRequest.

private static IndividualRequest fakeIndRequest(String url, Map<String, String> headers, Map<String, IndividualRequest> dependentRequests) {
    IndividualRequest individualRequest = new IndividualRequest();
    individualRequest.setMethod(HttpMethod.GET.name());
    individualRequest.setRelativeUrl(url);
    if (headers != null && headers.size() > 0) {
        individualRequest.setHeaders(new StringMap(headers));
    }
    individualRequest.setDependentRequests(new IndividualRequestMap(dependentRequests));
    return individualRequest;
}
Also used : IndividualRequest(com.linkedin.restli.common.multiplexer.IndividualRequest) IndividualRequestMap(com.linkedin.restli.common.multiplexer.IndividualRequestMap) StringMap(com.linkedin.data.template.StringMap)

Example 18 with IndividualRequest

use of com.linkedin.restli.common.multiplexer.IndividualRequest in project rest.li by linkedin.

the class TestMultiplexedRequestHandlerImpl method testResponseCookiesAggregated.

@Test(dataProvider = "multiplexerConfigurations")
public void testResponseCookiesAggregated(MultiplexerRunMode multiplexerRunMode) throws Exception {
    // Per security review: We should not make cookies for each individual responses visible to the client (especially if the cookie is HttpOnly).
    // Therefore all cookies returned by individual responses will be aggregated at the envelope response level.
    // Create a mockHandler. Make it return different cookies based on the request
    SynchronousRequestHandler mockHandler = new SynchronousRequestHandler() {

        @Override
        public RestResponse handleRequestSync(RestRequest request, RequestContext requestContext) {
            try {
                URI uri = request.getURI();
                RestResponseBuilder restResponseBuilder = new RestResponseBuilder();
                restResponseBuilder.setStatus(HttpStatus.S_200_OK.getCode());
                restResponseBuilder.setEntity(jsonBodyToByteString(fakeIndividualBody("don't care")));
                List<HttpCookie> cookies = new ArrayList<>();
                if (uri.getPath().contains("req1")) {
                    HttpCookie cookie = new HttpCookie("cookie1", "cookie1Value");
                    cookie.setDomain(".www.linkedin.com");
                    cookie.setSecure(false);
                    cookies.add(cookie);
                    HttpCookie commonCookie = new HttpCookie("commonCookie", "commonCookieValue");
                    commonCookie.setDomain(".WWW.linkedin.com");
                    commonCookie.setPath("/foo");
                    commonCookie.setSecure(false);
                    cookies.add(commonCookie);
                } else if (uri.getPath().contains("req2")) {
                    HttpCookie cookie = new HttpCookie("cookie2", "cookie2Value");
                    cookie.setDomain("www.linkedin.com");
                    cookie.setSecure(false);
                    cookies.add(cookie);
                    cookie = new HttpCookie("cookie3", "cookie3Value");
                    cookies.add(cookie);
                    HttpCookie commonCookie = new HttpCookie("commonCookie", "commonCookieValue");
                    commonCookie.setDomain(".www.linkedin.com");
                    commonCookie.setPath("/foo");
                    commonCookie.setSecure(true);
                    cookies.add(commonCookie);
                } else {
                    HttpCookie cookie = new HttpCookie("cookie2", "newCookie2Value");
                    cookie.setDomain("www.linkedin.com");
                    cookie.setSecure(true);
                    cookies.add(cookie);
                }
                return restResponseBuilder.setCookies(CookieUtil.encodeSetCookies(cookies)).build();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    };
    // Prepare request to mux handler
    FutureCallback<RestResponse> callback = new FutureCallback<>();
    RequestContext requestContext = new RequestContext();
    Map<String, IndividualRequest> individualRequests = ImmutableMap.of("0", fakeIndRequest("/req1"), "1", fakeIndRequest("/req2", ImmutableMap.of("2", fakeIndRequest("/req3"))));
    // Create mux handler instance
    MultiplexedRequestHandlerImpl multiplexer = createMultiplexer(mockHandler, null, Collections.<String>emptySet(), 3, multiplexerRunMode);
    try {
        multiplexer.handleRequest(fakeMuxRestRequest(individualRequests), requestContext, callback);
    } catch (Exception e) {
        fail("Multiplexer should not throw exception", e);
    }
    RestResponse muxRestResponse = callback.get();
    // assert multiplexed request should return a 200 status code
    assertEquals(muxRestResponse.getStatus(), 200, "Multiplexer should return 200");
    MultiplexedResponseContent muxResponseContent = new MultiplexedResponseContent(DataMapConverter.bytesToDataMap(muxRestResponse.getHeaders(), muxRestResponse.getEntity()));
    // individual response should not have set-cookie headers
    IndividualResponseMap responses = muxResponseContent.getResponses();
    for (IndividualResponse res : responses.values()) {
        for (String headerName : res.getHeaders().keySet()) {
            assertTrue(headerName.equalsIgnoreCase("set-cookie"), "Individual response header should not container set-cookie header: " + responses.toString());
        }
    }
    // Ensure cookies are aggregated at envelope level
    List<HttpCookie> cookies = CookieUtil.decodeSetCookies(muxRestResponse.getCookies());
    assertEquals(cookies.size(), 4);
    for (HttpCookie cookie : cookies) {
        if ("cookie1".equals(cookie.getName())) {
            assertEquals(cookie.getValue(), "cookie1Value");
            assertEquals(cookie.getDomain(), ".www.linkedin.com");
            assertEquals(cookie.getSecure(), false);
        } else if ("cookie2".equals(cookie.getName())) {
            assertEquals(cookie.getValue(), "newCookie2Value");
            assertEquals(cookie.getDomain(), "www.linkedin.com");
            assertEquals(cookie.getSecure(), true);
        } else if ("cookie3".equals(cookie.getName())) {
            assertEquals(cookie.getValue(), "cookie3Value");
        } else if ("commonCookie".equals(cookie.getName())) {
            assertEquals(cookie.getValue(), "commonCookieValue");
            assertEquals(cookie.getDomain().toLowerCase(), ".www.linkedin.com");
            assertEquals(cookie.getPath(), "/foo");
        // Since request0 and request1 are executed in parallel, depending on which request is completed first,
        // we don't know what will be its final 'secure' attribute value.
        } else {
            fail("Unknown cookie name: " + cookie.getName());
        }
    }
}
Also used : MultiplexedResponseContent(com.linkedin.restli.common.multiplexer.MultiplexedResponseContent) RestResponse(com.linkedin.r2.message.rest.RestResponse) RestResponseBuilder(com.linkedin.r2.message.rest.RestResponseBuilder) ArrayList(java.util.ArrayList) ByteString(com.linkedin.data.ByteString) URI(java.net.URI) IndividualResponse(com.linkedin.restli.common.multiplexer.IndividualResponse) URISyntaxException(java.net.URISyntaxException) RestLiServiceException(com.linkedin.restli.server.RestLiServiceException) RestException(com.linkedin.r2.message.rest.RestException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) IndividualRequest(com.linkedin.restli.common.multiplexer.IndividualRequest) RestRequest(com.linkedin.r2.message.rest.RestRequest) RequestContext(com.linkedin.r2.message.RequestContext) HttpCookie(java.net.HttpCookie) IndividualResponseMap(com.linkedin.restli.common.multiplexer.IndividualResponseMap) FutureCallback(com.linkedin.common.callback.FutureCallback) Test(org.testng.annotations.Test)

Example 19 with IndividualRequest

use of com.linkedin.restli.common.multiplexer.IndividualRequest in project rest.li by linkedin.

the class TestMultiplexedRequestHandlerImpl method testIndividualRequestInheritHeadersAndCookiesFromEnvelopeRequest.

@Test(dataProvider = "multiplexerConfigurations")
public void testIndividualRequestInheritHeadersAndCookiesFromEnvelopeRequest(MultiplexerRunMode multiplexerRunMode) throws Exception {
    // When some request headers/cookies are passed in the envelope, we need to ensure
    // they are properly included in each of the individual requests sent to
    // MultiplexerSingletonFilter and request handler. In the high level, the expected behavior should be:
    // 1. IndividualRequest that is passed to MultiplexerSingletonFilter should already have headers inherited from the
    // envelope request.
    // 2. RestRequest that is passed to the request handler should have both headers and cookies inherited from the
    // envelope request.
    // Create a mockHandler. Captures all headers and cookies found in the request.
    final Map<String, String> headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
    final Map<String, String> cookies = new HashMap<>();
    SynchronousRequestHandler mockHandler = new SynchronousRequestHandler() {

        @Override
        public RestResponse handleRequestSync(RestRequest request, RequestContext requestContext) {
            try {
                headers.putAll(request.getHeaders());
                for (HttpCookie cookie : CookieUtil.decodeCookies(request.getCookies())) {
                    cookies.put(cookie.getName(), cookie.getValue());
                }
                return fakeIndRestResponse(jsonBodyToByteString(new IndividualBody()));
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    };
    // Create a mock MultiplexerSingletonFilter to put request headers inside another headers so
    // we can do assertion on it later.
    final Map<String, String> headersSeenInMuxFilter = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
    MultiplexerSingletonFilter muxFilterWithSimulatedFailures = new MultiplexerSingletonFilter() {

        @Override
        public IndividualRequest filterIndividualRequest(IndividualRequest request) {
            headersSeenInMuxFilter.putAll(request.getHeaders());
            return request;
        }

        @Override
        public IndividualResponse filterIndividualResponse(IndividualResponse response) {
            return response;
        }
    };
    // Prepare request to mux handler
    FutureCallback<RestResponse> callback = new FutureCallback<>();
    RequestContext requestContext = new RequestContext();
    Map<String, IndividualRequest> individualRequests = ImmutableMap.of("0", fakeIndRequest("/request", ImmutableMap.of("X-IndividualHeader", "individualHeader", "X-OverridableHeader", "overrideHeader"), Collections.<String, IndividualRequest>emptyMap()));
    Set<String> headerWhiteList = new HashSet<>();
    headerWhiteList.add("X-IndividualHeader");
    headerWhiteList.add("X-OverridableHeader");
    // Prepare mux request with cookie
    RestRequest muxRequest = new RestRequestBuilder(fakeMuxRestRequest(individualRequests)).addCookie("cookie1=cookie1Value; cookie2=cookie2Value").addHeaderValue("X-overridableheader", "originalHeader").addHeaderValue("X-Envelope", "envelopeHeaderValue").build();
    // Create mux handler instance
    MultiplexedRequestHandlerImpl multiplexer = createMultiplexer(mockHandler, muxFilterWithSimulatedFailures, headerWhiteList, individualRequests.size(), multiplexerRunMode);
    try {
        multiplexer.handleRequest(muxRequest, requestContext, callback);
    } catch (Exception e) {
        fail("Multiplexer should not throw exception", e);
    }
    RestResponse muxRestResponse = callback.get();
    // Assert multiplexed request should return a 200 status code
    assertEquals(muxRestResponse.getStatus(), 200, "Multiplexer should return 200");
    MultiplexedResponseContent muxResponseContent = new MultiplexedResponseContent(DataMapConverter.bytesToDataMap(muxRestResponse.getHeaders(), muxRestResponse.getEntity()));
    IndividualResponse response = muxResponseContent.getResponses().get("0");
    assertEquals(response.getStatus().intValue(), 200, "Individual request should not fail. Response body is: " + response.getBody().toString());
    Map<String, String> expectedHeaders = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
    expectedHeaders.putAll(ImmutableMap.of(RestConstants.HEADER_CONTENT_TYPE, RestConstants.HEADER_VALUE_APPLICATION_JSON, "X-IndividualHeader", "individualHeader", "X-OverridableHeader", "overrideHeader", "X-Envelope", "envelopeHeaderValue"));
    Map<String, String> expectedCookies = ImmutableMap.of("cookie1", "cookie1Value", "cookie2", "cookie2Value");
    assertEquals(headers.size(), expectedHeaders.size(), "Incorrect numnber of headers, found:" + headers.toString());
    assertEquals(cookies.size(), expectedCookies.size(), "Incorrect numnber of cookies, found:" + cookies.toString());
    assertEquals(headersSeenInMuxFilter.size(), expectedHeaders.size(), "Incorrect numnber of headers seen by Mux filter, found:" + headers.toString());
    for (Map.Entry<String, String> header : headers.entrySet()) {
        assertEquals(header.getValue(), expectedHeaders.get(header.getKey()), "Incorrect header value for header: " + header.getKey());
    }
    for (Map.Entry<String, String> cookie : cookies.entrySet()) {
        assertEquals(cookie.getValue(), expectedCookies.get(cookie.getKey()), "Incorrect cookie value for cookie: " + cookie.getKey());
    }
    for (Map.Entry<String, String> header : headersSeenInMuxFilter.entrySet()) {
        assertEquals(header.getValue(), expectedHeaders.get(header.getKey()), "Incorrect header value for header seen by Mux Filter: " + header.getKey());
    }
}
Also used : MultiplexedResponseContent(com.linkedin.restli.common.multiplexer.MultiplexedResponseContent) HashMap(java.util.HashMap) ByteString(com.linkedin.data.ByteString) IndividualBody(com.linkedin.restli.common.multiplexer.IndividualBody) RequestContext(com.linkedin.r2.message.RequestContext) FutureCallback(com.linkedin.common.callback.FutureCallback) HashSet(java.util.HashSet) RestResponse(com.linkedin.r2.message.rest.RestResponse) TreeMap(java.util.TreeMap) IndividualResponse(com.linkedin.restli.common.multiplexer.IndividualResponse) URISyntaxException(java.net.URISyntaxException) RestLiServiceException(com.linkedin.restli.server.RestLiServiceException) RestException(com.linkedin.r2.message.rest.RestException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) IndividualRequest(com.linkedin.restli.common.multiplexer.IndividualRequest) RestRequest(com.linkedin.r2.message.rest.RestRequest) RestRequestBuilder(com.linkedin.r2.message.rest.RestRequestBuilder) HttpCookie(java.net.HttpCookie) Map(java.util.Map) IndividualRequestMap(com.linkedin.restli.common.multiplexer.IndividualRequestMap) ImmutableMap(com.google.common.collect.ImmutableMap) HashMap(java.util.HashMap) DataMap(com.linkedin.data.DataMap) StringMap(com.linkedin.data.template.StringMap) IndividualResponseMap(com.linkedin.restli.common.multiplexer.IndividualResponseMap) TreeMap(java.util.TreeMap) Test(org.testng.annotations.Test)

Example 20 with IndividualRequest

use of com.linkedin.restli.common.multiplexer.IndividualRequest in project rest.li by linkedin.

the class TestMultiplexedRequestHandlerImpl method testHandleTooManySequentialRequests.

@Test(dataProvider = "multiplexerConfigurations")
public void testHandleTooManySequentialRequests(MultiplexerRunMode multiplexerRunMode) throws Exception {
    // MultiplexedRequestHandlerImpl is created with the request limit set to 2
    MultiplexedRequestHandlerImpl multiplexer = createMultiplexer(null, multiplexerRunMode);
    IndividualRequest ir2 = fakeIndRequest(FOO_URL);
    IndividualRequest ir1 = fakeIndRequest(FOO_URL, ImmutableMap.of("2", ir2));
    IndividualRequest ir0 = fakeIndRequest(FOO_URL, ImmutableMap.of("1", ir1));
    RestRequest request = fakeMuxRestRequest(ImmutableMap.of("0", ir0));
    FutureCallback<RestResponse> callback = new FutureCallback<>();
    multiplexer.handleRequest(request, new RequestContext(), callback);
    assertEquals(getErrorStatus(callback), HttpStatus.S_400_BAD_REQUEST);
}
Also used : IndividualRequest(com.linkedin.restli.common.multiplexer.IndividualRequest) RestRequest(com.linkedin.r2.message.rest.RestRequest) RestResponse(com.linkedin.r2.message.rest.RestResponse) RequestContext(com.linkedin.r2.message.RequestContext) FutureCallback(com.linkedin.common.callback.FutureCallback) Test(org.testng.annotations.Test)

Aggregations

IndividualRequest (com.linkedin.restli.common.multiplexer.IndividualRequest)21 IndividualRequestMap (com.linkedin.restli.common.multiplexer.IndividualRequestMap)12 Test (org.testng.annotations.Test)12 RequestContext (com.linkedin.r2.message.RequestContext)9 RestRequest (com.linkedin.r2.message.rest.RestRequest)9 FutureCallback (com.linkedin.common.callback.FutureCallback)7 StringMap (com.linkedin.data.template.StringMap)7 RestResponse (com.linkedin.r2.message.rest.RestResponse)7 ByteString (com.linkedin.data.ByteString)5 RestException (com.linkedin.r2.message.rest.RestException)4 MultiplexedResponseContent (com.linkedin.restli.common.multiplexer.MultiplexedResponseContent)4 RestLiServiceException (com.linkedin.restli.server.RestLiServiceException)4 IOException (java.io.IOException)4 URISyntaxException (java.net.URISyntaxException)4 HashMap (java.util.HashMap)4 ExecutionException (java.util.concurrent.ExecutionException)4 IndividualResponse (com.linkedin.restli.common.multiplexer.IndividualResponse)3 IndividualResponseMap (com.linkedin.restli.common.multiplexer.IndividualResponseMap)3 MultiplexedRequestContent (com.linkedin.restli.common.multiplexer.MultiplexedRequestContent)3 HttpCookie (java.net.HttpCookie)3