use of com.linkedin.r2.message.rest.RestResponseBuilder in project rest.li by linkedin.
the class ResponseUtils method buildResponse.
public static RestResponse buildResponse(RoutingResult routingResult, RestLiResponse restLiResponse) {
RestResponseBuilder builder = new RestResponseBuilder().setHeaders(restLiResponse.getHeaders()).setCookies(CookieUtil.encodeSetCookies(restLiResponse.getCookies())).setStatus(restLiResponse.getStatus().getCode());
ServerResourceContext context = routingResult.getContext();
ResourceEntityType resourceEntityType = routingResult.getResourceMethod().getResourceModel().getResourceEntityType();
if (restLiResponse.hasData() && ResourceEntityType.STRUCTURED_DATA == resourceEntityType) {
DataMap dataMap = restLiResponse.getDataMap();
String mimeType = context.getResponseMimeType();
URI requestUri = context.getRequestURI();
Map<String, String> requestHeaders = context.getRequestHeaders();
builder = encodeResult(mimeType, requestUri, requestHeaders, builder, dataMap);
}
return builder.build();
}
use of com.linkedin.r2.message.rest.RestResponseBuilder 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());
}
}
}
use of com.linkedin.r2.message.rest.RestResponseBuilder in project rest.li by linkedin.
the class TestRestLiServer method testRequestHandlers.
@Test(dataProvider = "requestHandlersData")
public void testRequestHandlers(URI uri, String expectedResponse) {
RestLiConfig config = new RestLiConfig();
config.addResourcePackageNames("com.linkedin.restli.server.twitter");
config.setDocumentationRequestHandler(new DefaultDocumentationRequestHandler() {
@Override
public void initialize(RestLiConfig config, Map<String, ResourceModel> rootResources) {
/* no-op */
}
@Override
public void handleRequest(RestRequest req, RequestContext ctx, Callback<RestResponse> cb) {
cb.onSuccess(new RestResponseBuilder().setEntity(toByteString(DOCUMENTATION_RESPONSE)).build());
}
});
config.addCustomRequestHandlers(new CustomRequestHandler());
config.addDebugRequestHandlers(new DebugRequestHandler("a", DEBUG_HANDLER_RESPONSE_A), new DebugRequestHandler("b", DEBUG_HANDLER_RESPONSE_B));
RestLiServer server = new RestLiServer(config, new EasyMockResourceFactory(), createMock(Engine.class));
RestRequest restReq = new RestRequestBuilder(uri).build();
server.handleRequest(restReq, createMock(RequestContext.class), new RestResponseAssertionCallback(expectedResponse));
StreamRequest streamReq = new StreamRequestBuilder(uri).build(EntityStreams.emptyStream());
server.handleRequest(streamReq, createMock(RequestContext.class), new StreamResponseAssertionCallback(expectedResponse));
}
use of com.linkedin.r2.message.rest.RestResponseBuilder in project rest.li by linkedin.
the class TestRestLiCallback method testOnSuccessBuildPartialResponseFailure.
@Test
@SuppressWarnings("unchecked")
public void testOnSuccessBuildPartialResponseFailure() throws Exception {
String result = "foo";
RestLiResponseData<UpdateResponseEnvelope> responseData = ResponseDataBuilderUtil.buildUpdateResponseData(HttpStatus.S_200_OK);
RestResponse restResponse = new RestResponseBuilder().build();
// Set up.
when((RestLiResponseData<UpdateResponseEnvelope>) _responseHandler.buildRestLiResponseData(_restRequest, _routingResult, result)).thenReturn(responseData);
Exception e = new RuntimeException("Error1");
when(_responseHandler.buildPartialResponse(_routingResult, responseData)).thenThrow(e);
// Invoke.
_noFilterRestLiCallback.onSuccess(result);
// Verify.
verify(_responseHandler).buildPartialResponse(_routingResult, responseData);
verify(_responseHandler).buildRestLiResponseData(_restRequest, _routingResult, result);
ArgumentCaptor<RestLiResponseException> partialRestResponseExceptionCaptor = ArgumentCaptor.forClass(RestLiResponseException.class);
verify(_callback).onError(partialRestResponseExceptionCaptor.capture());
verifyZeroInteractions(_restRequest);
verifyNoMoreInteractions(_responseHandler, _callback);
RestLiResponse restLiResponse = partialRestResponseExceptionCaptor.getValue().getRestLiResponse();
assertEquals(restLiResponse.getStatus(), HttpStatus.S_500_INTERNAL_SERVER_ERROR);
assertEquals(RestConstants.HEADER_VALUE_ERROR, restLiResponse.getHeader(HeaderUtil.getErrorResponseHeaderName(Collections.emptyMap())));
}
use of com.linkedin.r2.message.rest.RestResponseBuilder in project rest.li by linkedin.
the class TestRestLiSymbolTableProvider method testGetRemoteRequestSymbolTableFetchNon404Error.
@Test
public void testGetRemoteRequestSymbolTableFetchNon404Error() {
AtomicInteger networkCallCount = new AtomicInteger(0);
RestResponseBuilder builder = new RestResponseBuilder();
builder.setStatus(500);
when(_client.restRequest(eq(new RestRequestBuilder(URI.create("d2://serviceName/symbolTable")).setHeaders(Collections.singletonMap(RestConstants.HEADER_FETCH_SYMBOL_TABLE, Boolean.TRUE.toString())).build()))).thenAnswer(invocation -> {
networkCallCount.incrementAndGet();
return CompletableFuture.completedFuture(builder.build());
});
// First fetch should trigger a network request.
Assert.assertNull(_provider.getRequestSymbolTable(URI.create("d2://serviceName")));
Assert.assertEquals(networkCallCount.get(), 1);
// Subsequent fetch should also trigger a network request because response should not have been cached.
Assert.assertNull(_provider.getRequestSymbolTable(URI.create("d2://serviceName")));
Assert.assertEquals(networkCallCount.get(), 2);
}
Aggregations