use of com.linkedin.restli.server.filter.Filter in project rest.li by linkedin.
the class TestCustomContextData method testUpdateCustomData.
@Test
public void testUpdateCustomData() throws RemoteInvocationException, IOException {
List<Filter> filters = Arrays.asList(new TestFilter());
init(filters);
RootBuilderWrapper<Long, Greeting> builders = new RootBuilderWrapper<>(new GreetingsBuilders());
final Request<Object> req = builders.action("modifyCustomContext").build();
Response<Object> response = getClient().sendRequest(req).getResponse();
Assert.assertEquals(response.getStatus(), HttpStatus.S_200_OK.getCode());
}
use of com.linkedin.restli.server.filter.Filter in project rest.li by linkedin.
the class TestResponseCompression method initClass.
@BeforeClass
public void initClass() throws Exception {
class TestHelperFilter implements Filter {
@Override
public CompletableFuture<Void> onRequest(FilterRequestContext requestContext) {
Map<String, String> requestHeaders = requestContext.getRequestHeaders();
if (requestHeaders.containsKey(EXPECTED_ACCEPT_ENCODING)) {
String expected = requestHeaders.get(EXPECTED_ACCEPT_ENCODING);
if (expected.equals(NONE)) {
if (requestHeaders.containsKey(HttpConstants.ACCEPT_ENCODING)) {
throw new RestLiServiceException(HttpStatus.S_400_BAD_REQUEST, "Accept-Encoding header should not be present.");
}
} else {
if (!expected.equals(requestHeaders.get(HttpConstants.ACCEPT_ENCODING))) {
throw new RestLiServiceException(HttpStatus.S_400_BAD_REQUEST, "Accept-Encoding header should be " + expected + ", but received " + requestHeaders.get(HttpConstants.ACCEPT_ENCODING));
}
}
}
if (requestHeaders.containsKey(EXPECTED_COMPRESSION_THRESHOLD)) {
if (!requestHeaders.get(EXPECTED_COMPRESSION_THRESHOLD).equals(requestHeaders.get(HttpConstants.HEADER_RESPONSE_COMPRESSION_THRESHOLD))) {
throw new RestLiServiceException(HttpStatus.S_400_BAD_REQUEST, "Expected " + HttpConstants.HEADER_RESPONSE_COMPRESSION_THRESHOLD + " " + requestHeaders.get(EXPECTED_COMPRESSION_THRESHOLD) + ", but received " + requestHeaders.get(HttpConstants.HEADER_RESPONSE_COMPRESSION_THRESHOLD));
}
}
return CompletableFuture.completedFuture(null);
}
}
// The default compression threshold is between tiny and huge threshold.
final FilterChain fc = FilterChains.empty().addLastRest(new TestCompressionServer.SaveContentEncodingHeaderFilter()).addLastRest(new ServerCompressionFilter("x-snappy-framed,snappy,gzip,deflate", new CompressionConfig(10000))).addLastRest(new SimpleLoggingFilter());
super.init(Arrays.asList(new TestHelperFilter()), fc, false);
}
use of com.linkedin.restli.server.filter.Filter in project rest.li by linkedin.
the class ErrorResponseValidationFilter method onError.
@Override
public CompletableFuture<Void> onError(Throwable throwable, final FilterRequestContext requestContext, final FilterResponseContext responseContext) {
CompletableFuture<Void> future = new CompletableFuture<>();
if (throwable instanceof RestLiServiceException) {
RestLiServiceException restLiServiceException = (RestLiServiceException) throwable;
// do the validation only if the 'code' field is set on RestLiServiceException.
if (restLiServiceException.hasCode()) {
List<ServiceError> methodServiceErrors = requestContext.getMethodServiceErrors();
List<ServiceError> resourceServiceErrors = requestContext.getFilterResourceModel().getServiceErrors();
// nor on the method level skip the validation.
if (methodServiceErrors == null && resourceServiceErrors == null) {
// error details should not be set on RestLiServiceException object.
if (restLiServiceException.getErrorDetailsRecord() != null) {
return completeExceptionallyWithHttp500(future, restLiServiceException);
}
future.completeExceptionally(restLiServiceException);
return future;
}
Set<ServiceError> serviceErrors = new HashSet<>();
if (methodServiceErrors != null) {
serviceErrors.addAll(methodServiceErrors);
}
if (resourceServiceErrors != null) {
serviceErrors.addAll(resourceServiceErrors);
}
// An empty list of codes means that any service error code will result in a Http 500 error response.
if (serviceErrors.isEmpty()) {
return completeExceptionallyWithHttp500(future, restLiServiceException);
}
String errorCode = restLiServiceException.getCode();
Optional<ServiceError> maybeServiceError = serviceErrors.stream().filter(serviceError -> serviceError.code().equals(errorCode)).findFirst();
// convert given throwable to 500_INTERNAL_SERVER_ERROR exception.
if (!maybeServiceError.isPresent()) {
return completeExceptionallyWithHttp500(future, restLiServiceException);
}
ServiceError definedServiceError = maybeServiceError.get();
// Check that the error detail type is valid.
if (restLiServiceException.hasErrorDetails()) {
Class<?> errorResponseErrorDetailType = restLiServiceException.getErrorDetailsRecord().getClass();
Class<?> definedErrorDetailType = definedServiceError.errorDetailType();
if (!errorResponseErrorDetailType.equals(definedErrorDetailType)) {
return completeExceptionallyWithHttp500(future, restLiServiceException);
}
}
// convert given throwable to 500_INTERNAL_SERVER_ERROR exception.
if (definedServiceError.httpStatus() != restLiServiceException.getStatus()) {
return completeExceptionallyWithHttp500(future, restLiServiceException);
}
// TODO: validate error message. What if the defined message in service error has placeholders, which gets filled based on some business logic in the code.
}
}
future.completeExceptionally(throwable);
return future;
}
use of com.linkedin.restli.server.filter.Filter in project rest.li by linkedin.
the class TestRestLiMethodInvocation method testInvokerWithFilters.
@Test(dataProvider = "provideFilterConfig")
public void testInvokerWithFilters(final boolean throwExceptionFromFirstFilter) throws Exception {
RestLiArgumentBuilder mockArgumentBuilder = createMock(RestLiArgumentBuilder.class);
Filter mockFilter = createMock(Filter.class);
@SuppressWarnings("unchecked") Callback<Object> mockCallback = createMock(Callback.class);
FilterRequestContext mockFilterContext = createMock(FilterRequestContext.class);
RestLiRequestData requestData = new RestLiRequestDataImpl.Builder().key("Key").build();
RestLiMethodInvoker invokerWithFilters = new RestLiMethodInvoker(_resourceFactory, _engine, ErrorResponseBuilder.DEFAULT_INTERNAL_ERROR_MESSAGE);
Map<String, ResourceModel> resourceModelMap = buildResourceModels(StatusCollectionResource.class, LocationResource.class, DiscoveredItemsResource.class);
ResourceModel statusResourceModel = resourceModelMap.get("/statuses");
ResourceMethodDescriptor resourceMethodDescriptor = statusResourceModel.findMethod(ResourceMethod.GET);
final StatusCollectionResource resource = getMockResource(StatusCollectionResource.class);
RestRequestBuilder builder = new RestRequestBuilder(new URI("/statuses/1")).setMethod("GET").addHeaderValue("Accept", "application/json").setHeader(RestConstants.HEADER_RESTLI_PROTOCOL_VERSION, AllProtocolVersions.LATEST_PROTOCOL_VERSION.toString());
RestRequest request = builder.build();
RoutingResult routingResult = new RoutingResult(new ResourceContextImpl(buildPathKeys("statusID", 1L), request, new RequestContext()), resourceMethodDescriptor);
expectLastCall();
FilterChainDispatcher filterChainDispatcher = new FilterChainDispatcher() {
@Override
public void onRequestSuccess(RestLiRequestData requestData, RestLiCallback restLiCallback) {
// only invoke if filter chain's requests were successful
invokerWithFilters.invoke(requestData, routingResult, mockArgumentBuilder, restLiCallback);
}
};
FilterChainCallback filterChainCallback = new FilterChainCallback() {
@Override
public void onResponseSuccess(RestLiResponseData<?> responseData) {
// unused
}
@Override
public void onError(Throwable th, RestLiResponseData<?> responseData) {
// unused
}
};
final Exception exFromFilter = new RuntimeException("Exception from filter!");
if (throwExceptionFromFirstFilter) {
mockFilter.onRequest(eq(mockFilterContext));
expectLastCall().andThrow(exFromFilter);
mockCallback.onError(eq(exFromFilter));
} else {
expect(mockFilterContext.getRequestData()).andReturn(requestData).times(3);
mockFilter.onRequest(eq(mockFilterContext));
expectLastCall().andAnswer(new IAnswer<Object>() {
@Override
public Object answer() throws Throwable {
FilterRequestContext filterContext = (FilterRequestContext) getCurrentArguments()[0];
RestLiRequestData data = filterContext.getRequestData();
// Verify incoming data.
assertEquals(data.getKey(), "Key");
// Update data.
data.setKey("Key-Filter1");
return CompletableFuture.completedFuture(null);
}
}).andAnswer(new IAnswer<Object>() {
@Override
public Object answer() throws Throwable {
FilterRequestContext filterContext = (FilterRequestContext) getCurrentArguments()[0];
RestLiRequestData data = filterContext.getRequestData();
// Verify incoming data.
assertEquals(data.getKey(), "Key-Filter1");
// Update data.
data.setKey("Key-Filter2");
return CompletableFuture.completedFuture(null);
}
});
Long[] argsArray = { 1L };
expect(mockArgumentBuilder.buildArguments(requestData, routingResult)).andReturn(argsArray);
expect(resource.get(eq(1L))).andReturn(null).once();
mockCallback.onSuccess(eq(null));
}
replay(resource, mockArgumentBuilder, mockFilterContext, mockFilter, mockCallback);
RestUtils.validateRequestHeadersAndUpdateResourceContext(request.getHeaders(), Collections.emptySet(), routingResult.getContext());
RestLiFilterChain filterChain = new RestLiFilterChain(Arrays.asList(mockFilter, mockFilter), filterChainDispatcher, filterChainCallback);
filterChain.onRequest(mockFilterContext, new RestLiFilterResponseContextFactory(request, routingResult, new RestLiResponseHandler(_methodAdapterProvider, _errorResponseBuilder)));
verifyRecording(mockArgumentBuilder, mockFilterContext, mockFilter);
if (throwExceptionFromFirstFilter) {
assertEquals(requestData.getKey(), "Key");
} else {
assertEquals(requestData.getKey(), "Key-Filter2");
verify(resource);
}
EasyMock.reset(resource);
EasyMock.makeThreadSafe(resource, true);
}
Aggregations