Search in sources :

Example 1 with IndividualResponseMap

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

the class MultiplexedCallback method notifyIndividualCallbacks.

private void notifyIndividualCallbacks(Response<MultiplexedResponseContent> muxResponse) {
    IndividualResponseMap individualResponses = muxResponse.getEntity().getResponses();
    for (IndividualResponseMap.Entry<String, IndividualResponse> individualResponseMapEntry : individualResponses.entrySet()) {
        Integer id = Integer.valueOf(individualResponseMapEntry.getKey());
        IndividualResponse individualResponse = individualResponseMapEntry.getValue();
        Callback<RestResponse> callback = _callbacks.get(id);
        RestResponse individualRestResponse;
        try {
            individualRestResponse = buildIndividualRestResponse(muxResponse, individualResponse);
        } catch (MimeTypeParseException e) {
            callback.onError(new RestLiDecodingException("Could not convert IndividualResponse to individual RestRestponse due to an invalid content type, id=" + id, e));
            return;
        } catch (IOException e) {
            callback.onError(new RestLiDecodingException("Could not convert IndividualResponse to individual RestRestponse, id=" + id, e));
            return;
        }
        if (RestStatus.isOK(individualResponse.getStatus())) {
            callback.onSuccess(individualRestResponse);
        } else {
            RestException exception = new RestException(individualRestResponse, "Received error " + individualRestResponse.getStatus());
            callback.onError(exception);
        }
    }
}
Also used : MimeTypeParseException(javax.activation.MimeTypeParseException) RestResponse(com.linkedin.r2.message.rest.RestResponse) RestException(com.linkedin.r2.message.rest.RestException) RestLiDecodingException(com.linkedin.restli.client.RestLiDecodingException) ByteString(com.linkedin.data.ByteString) IOException(java.io.IOException) IndividualResponseMap(com.linkedin.restli.common.multiplexer.IndividualResponseMap) IndividualResponse(com.linkedin.restli.common.multiplexer.IndividualResponse)

Example 2 with IndividualResponseMap

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

the class TestMultiplexedCallback method testMixed.

@Test
public void testMixed() throws Exception {
    FutureCallback<RestResponse> callback1 = new FutureCallback<RestResponse>();
    FutureCallback<RestResponse> callback2 = new FutureCallback<RestResponse>();
    ImmutableMap<Integer, Callback<RestResponse>> individualCallbacks = ImmutableMap.<Integer, Callback<RestResponse>>of(ID1, callback1, ID2, callback2);
    FutureCallback<MultiplexedResponse> aggregatedCallback = new FutureCallback<MultiplexedResponse>();
    TestRecord entity1 = fakeEntity(ID1);
    IndividualResponse ir1 = fakeIndividualResponse(entity1);
    IndividualResponse ir2 = fakeIndividualErrorResponse();
    MultiplexedResponseContent responseContent = new MultiplexedResponseContent().setResponses(new IndividualResponseMap(ImmutableMap.of(Integer.toString(ID1), ir1, Integer.toString(ID2), ir2)));
    MultiplexedCallback multiplexedCallback = new MultiplexedCallback(individualCallbacks, aggregatedCallback);
    multiplexedCallback.onSuccess(fakeRestResponse(responseContent));
    assertRestResponseEquals(callback1.get(), fakeRestResponse(entity1));
    RestException actualError = (RestException) getError(callback2);
    assertRestResponseEquals(actualError.getResponse(), fakeRestErrorResponse());
    MultiplexedResponse multiplexedResponse = aggregatedCallback.get();
    Assert.assertEquals(multiplexedResponse.getStatus(), HttpStatus.S_200_OK.getCode());
    Assert.assertEquals(multiplexedResponse.getHeaders(), HEADERS);
}
Also used : MultiplexedResponseContent(com.linkedin.restli.common.multiplexer.MultiplexedResponseContent) RestResponse(com.linkedin.r2.message.rest.RestResponse) RestException(com.linkedin.r2.message.rest.RestException) IndividualResponse(com.linkedin.restli.common.multiplexer.IndividualResponse) FutureCallback(com.linkedin.common.callback.FutureCallback) Callback(com.linkedin.common.callback.Callback) TestRecord(com.linkedin.restli.client.test.TestRecord) IndividualResponseMap(com.linkedin.restli.common.multiplexer.IndividualResponseMap) FutureCallback(com.linkedin.common.callback.FutureCallback) Test(org.testng.annotations.Test)

Example 3 with IndividualResponseMap

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

the class TestMultiplexedRequestHandlerImpl method testMultiplexedSingletonFilterFailures.

@Test(dataProvider = "multiplexerConfigurations")
public void testMultiplexedSingletonFilterFailures(MultiplexerRunMode multiplexerRunMode) throws Exception {
    // This test validates when a failure occurred in MultiplexedSingletonFilter for an individual request, only the individual
    // request should fail. The multiplexed request should still be completed successfully with a 200 status code.
    // Setup mock request handler: make handler return a json that contains the request uri
    // We are using this uri in our mock MultiplexerSingletonFilter.filterIndividualResponse function so that
    // we can simulate different response based on the request.
    SynchronousRequestHandler mockHandler = new SynchronousRequestHandler() {

        @Override
        public RestResponse handleRequestSync(RestRequest request, RequestContext requestContext) {
            try {
                return fakeIndRestResponse(jsonBodyToByteString(fakeIndividualBody(request.getURI().toString())));
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    };
    // Create a mock MultiplexerSingletonFilter to it simulate different type of failures.
    // Failure is simulated are base on the request uri.
    MultiplexerSingletonFilter muxFilterWithSimulatedFailures = new MultiplexerSingletonFilter() {

        @Override
        public IndividualRequest filterIndividualRequest(IndividualRequest request) {
            if (request.getRelativeUrl().contains("bad_request")) {
                throw new RestLiServiceException(HttpStatus.S_400_BAD_REQUEST, "not found");
            } else if (request.getRelativeUrl().contains("error_request")) {
                throw new IllegalArgumentException("Something really bad happened in filterIndividualRequest");
            }
            return request;
        }

        @Override
        public IndividualResponse filterIndividualResponse(IndividualResponse response) {
            if (response.getStatus() == HttpStatus.S_200_OK.getCode()) {
                if (response.getBody().data().getString("value").contains("notfound_response")) {
                    throw new RestLiServiceException(HttpStatus.S_404_NOT_FOUND, "not found");
                } else if (response.getBody().data().getString("value").contains("error_response")) {
                    // simulate an unexpected exception
                    throw new UnsupportedOperationException("Something really bad happened in filterIndividualResponse");
                }
            }
            return response;
        }
    };
    // Prepare request to mux handler
    FutureCallback<RestResponse> callback = new FutureCallback<RestResponse>();
    RequestContext requestContext = new RequestContext();
    Map<String, IndividualRequest> individualRequests = new HashMap<String, IndividualRequest>();
    individualRequests.put("0", fakeIndRequest("/good_request"));
    individualRequests.put("1", fakeIndRequest("/bad_request"));
    individualRequests.put("2", fakeIndRequest("/error_request"));
    individualRequests.put("3", fakeIndRequest("/notfound_response"));
    individualRequests.put("4", fakeIndRequest("/error_response"));
    individualRequests.put("5", fakeIndRequest("/good_request", ImmutableMap.of("6", fakeIndRequest("/bad_request"))));
    RestRequest request = fakeMuxRestRequest(individualRequests);
    // Create mux handler instance
    MultiplexedRequestHandlerImpl multiplexer = createMultiplexer(mockHandler, muxFilterWithSimulatedFailures, Collections.<String>emptySet(), 10, multiplexerRunMode);
    try {
        multiplexer.handleRequest(request, requestContext, callback);
    } catch (Exception e) {
        fail("Multiplexer should not blow up because one of the individual requests failed", e);
    }
    RestResponse muxRestResponse = callback.get();
    // Assert multiplexed request should return a 200 status code
    assertEquals(muxRestResponse.getStatus(), 200, "Failure in indivudal request should not cause the entire multliplexed request to fail");
    MultiplexedResponseContent muxResponseContent = new MultiplexedResponseContent(DataMapConverter.bytesToDataMap(muxRestResponse.getHeaders(), muxRestResponse.getEntity()));
    IndividualResponseMap responses = muxResponseContent.getResponses();
    // Validate the status code for each of the response
    assertEquals(responses.get("0").getStatus().intValue(), 200, "Mux response body is: " + responses.toString());
    assertEquals(responses.get("1").getStatus().intValue(), 400, "Mux response body is: " + responses.toString());
    assertEquals(responses.get("2").getStatus().intValue(), 500, "Mux response body is: " + responses.toString());
    assertEquals(responses.get("3").getStatus().intValue(), 404, "Mux response body is: " + responses.toString());
    assertEquals(responses.get("4").getStatus().intValue(), 500, "Mux response body is: " + responses.toString());
    assertEquals(responses.get("5").getStatus().intValue(), 200, "Mux response body is: " + responses.toString());
    assertEquals(responses.get("6").getStatus().intValue(), 400, "Mux response body is: " + responses.toString());
}
Also used : MultiplexedResponseContent(com.linkedin.restli.common.multiplexer.MultiplexedResponseContent) HashMap(java.util.HashMap) RestResponse(com.linkedin.r2.message.rest.RestResponse) ByteString(com.linkedin.data.ByteString) 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) RestLiServiceException(com.linkedin.restli.server.RestLiServiceException) RequestContext(com.linkedin.r2.message.RequestContext) IndividualResponseMap(com.linkedin.restli.common.multiplexer.IndividualResponseMap) FutureCallback(com.linkedin.common.callback.FutureCallback) Test(org.testng.annotations.Test)

Example 4 with IndividualResponseMap

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

the class TestMultiplexedRequestHandlerImpl method fakeMuxRestResponse.

private static RestResponse fakeMuxRestResponse(Map<Integer, IndividualResponse> responses) throws IOException {
    IndividualResponseMap individualResponseMap = new IndividualResponseMap();
    for (Map.Entry<Integer, IndividualResponse> responseMapEntry : responses.entrySet()) {
        individualResponseMap.put(Integer.toString(responseMapEntry.getKey()), responseMapEntry.getValue());
    }
    MultiplexedResponseContent content = new MultiplexedResponseContent();
    content.setResponses(individualResponseMap);
    return new RestResponseBuilder().setStatus(HttpStatus.S_200_OK.getCode()).setEntity(CODEC.mapToBytes(content.data())).build();
}
Also used : MultiplexedResponseContent(com.linkedin.restli.common.multiplexer.MultiplexedResponseContent) RestResponseBuilder(com.linkedin.r2.message.rest.RestResponseBuilder) IndividualResponseMap(com.linkedin.restli.common.multiplexer.IndividualResponseMap) 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) IndividualResponse(com.linkedin.restli.common.multiplexer.IndividualResponse)

Example 5 with IndividualResponseMap

use of com.linkedin.restli.common.multiplexer.IndividualResponseMap 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<HttpCookie>();
                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<RestResponse>();
    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)

Aggregations

IndividualResponseMap (com.linkedin.restli.common.multiplexer.IndividualResponseMap)7 RestResponse (com.linkedin.r2.message.rest.RestResponse)6 IndividualResponse (com.linkedin.restli.common.multiplexer.IndividualResponse)6 RestException (com.linkedin.r2.message.rest.RestException)5 MultiplexedResponseContent (com.linkedin.restli.common.multiplexer.MultiplexedResponseContent)5 FutureCallback (com.linkedin.common.callback.FutureCallback)4 Test (org.testng.annotations.Test)4 ByteString (com.linkedin.data.ByteString)3 IOException (java.io.IOException)3 HashMap (java.util.HashMap)3 Callback (com.linkedin.common.callback.Callback)2 RequestContext (com.linkedin.r2.message.RequestContext)2 RestRequest (com.linkedin.r2.message.rest.RestRequest)2 RestResponseBuilder (com.linkedin.r2.message.rest.RestResponseBuilder)2 TestRecord (com.linkedin.restli.client.test.TestRecord)2 IndividualRequest (com.linkedin.restli.common.multiplexer.IndividualRequest)2 IndividualRequestMap (com.linkedin.restli.common.multiplexer.IndividualRequestMap)2 RestLiServiceException (com.linkedin.restli.server.RestLiServiceException)2 HttpCookie (java.net.HttpCookie)2 URISyntaxException (java.net.URISyntaxException)2