use of com.linkedin.restli.common.attachments.RestLiAttachmentReader in project rest.li by linkedin.
the class TestArgumentBuilder method testRestLiAttachmentsParamResourceExpectNotPresent.
@Test
public void testRestLiAttachmentsParamResourceExpectNotPresent() {
// This test makes sure that a resource method that expects attachments, but none are present in the request,
// is given a null for the RestLiAttachmentReader.
ServerResourceContext mockResourceContext = EasyMock.createMock(ServerResourceContext.class);
EasyMock.expect(mockResourceContext.getRequestAttachmentReader()).andReturn(null);
EasyMock.replay(mockResourceContext);
@SuppressWarnings({ "unchecked", "rawtypes" }) final Parameter<RestLiAttachmentReader> param = new Parameter("RestLi Attachment Reader", RestLiAttachmentReader.class, null, false, null, Parameter.ParamType.RESTLI_ATTACHMENTS_PARAM, false, AnnotationSet.EMPTY);
List<Parameter<?>> parameters = Collections.singletonList(param);
Object[] results = ArgumentBuilder.buildArgs(new Object[0], getMockResourceMethod(parameters), mockResourceContext, null, getMockResourceMethodConfig(false));
Assert.assertEquals(results[0], null);
}
use of com.linkedin.restli.common.attachments.RestLiAttachmentReader in project rest.li by linkedin.
the class TestArgumentBuilder method testRestLiAttachmentsParamResourceNotExpect.
@Test
public void testRestLiAttachmentsParamResourceNotExpect() {
// This test makes sure that if the resource method did not expect attachments but there were attachments present
// in the request, that an exception is thrown.
ServerResourceContext mockResourceContext = EasyMock.createMock(ServerResourceContext.class);
final RestLiAttachmentReader restLiAttachmentReader = new RestLiAttachmentReader(null);
EasyMock.expect(mockResourceContext.getRequestAttachmentReader()).andReturn(restLiAttachmentReader);
EasyMock.replay(mockResourceContext);
List<Parameter<?>> parameters = Collections.emptyList();
try {
ArgumentBuilder.buildArgs(new Object[0], getMockResourceMethod(parameters), mockResourceContext, null, getMockResourceMethodConfig(false));
Assert.fail();
} catch (RestLiServiceException restLiServiceException) {
Assert.assertEquals(restLiServiceException.getStatus(), HttpStatus.S_400_BAD_REQUEST);
Assert.assertEquals(restLiServiceException.getMessage(), "Resource method endpoint invoked does not accept any request attachments.");
}
}
use of com.linkedin.restli.common.attachments.RestLiAttachmentReader in project rest.li by linkedin.
the class TestRestLiMethodInvocation method testStreaming.
@Test
public void testStreaming() throws Exception {
Map<String, ResourceModel> resourceModelMap = buildResourceModels(StatusCollectionResource.class, AsyncStatusCollectionResource.class, PromiseStatusCollectionResource.class, TaskStatusCollectionResource.class);
final String payload = "{\"metadata\": \"someMetadata\"}";
ResourceModel statusResourceModel = resourceModelMap.get("/statuses");
ResourceModel asyncStatusResourceModel = resourceModelMap.get("/asyncstatuses");
ResourceModel promiseStatusResourceModel = resourceModelMap.get("/promisestatuses");
ResourceModel taskStatusResourceModel = resourceModelMap.get("/taskstatuses");
ResourceMethodDescriptor methodDescriptor;
StatusCollectionResource statusResource;
AsyncStatusCollectionResource asyncStatusResource;
PromiseStatusCollectionResource promiseStatusResource;
TaskStatusCollectionResource taskStatusResource;
// Sync Method Execution - Successful scenario
methodDescriptor = statusResourceModel.findActionMethod("streamingAction", ResourceLevel.COLLECTION);
statusResource = getMockResource(StatusCollectionResource.class);
EasyMock.expect(statusResource.streamingAction(EasyMock.anyObject(), EasyMock.anyObject())).andReturn(1234l).once();
checkInvocation(statusResource, new RequestContext(), methodDescriptor, "POST", version, "/statuses/?action=streamingAction", payload, null, new Callback<RestResponse>() {
@Override
public void onError(Throwable e) {
Assert.fail("Request failed unexpectedly.");
}
@Override
public void onSuccess(RestResponse result) {
}
}, false, false, new RestLiAttachmentReader(null), new RestLiResponseAttachments.Builder().build());
// Sync Method Execution - Error scenario
statusResource = getMockResource(StatusCollectionResource.class);
EasyMock.expect(statusResource.streamingAction(EasyMock.anyObject(), EasyMock.anyObject())).andThrow(new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR)).once();
checkInvocation(statusResource, new RequestContext(), methodDescriptor, "POST", version, "/statuses/?action=streamingAction", payload, null, new Callback<RestResponse>() {
@Override
public void onError(Throwable e) {
}
@Override
public void onSuccess(RestResponse result) {
Assert.fail("Request passed unexpectedly.");
}
}, false, false, new RestLiAttachmentReader(null), new RestLiResponseAttachments.Builder().build());
// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Callback Method Execution - Successful scenario
methodDescriptor = asyncStatusResourceModel.findMethod(ResourceMethod.ACTION);
asyncStatusResource = getMockResource(AsyncStatusCollectionResource.class);
asyncStatusResource.streamingAction(EasyMock.anyObject(), EasyMock.anyObject(), EasyMock.anyObject());
EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
@Override
public Object answer() throws Throwable {
@SuppressWarnings("unchecked") Callback<Long> callback = (Callback<Long>) EasyMock.getCurrentArguments()[2];
callback.onSuccess(1234l);
return null;
}
});
checkInvocation(asyncStatusResource, new RequestContext(), methodDescriptor, "POST", version, "/asyncstatuses/?action=streamingAction", payload, null, new Callback<RestResponse>() {
@Override
public void onError(Throwable e) {
Assert.fail("Request failed unexpectedly.");
}
@Override
public void onSuccess(RestResponse result) {
}
}, false, false, new RestLiAttachmentReader(null), new RestLiResponseAttachments.Builder().build());
// Callback Method Execution - Error scenario
asyncStatusResource = getMockResource(AsyncStatusCollectionResource.class);
asyncStatusResource.streamingAction(EasyMock.anyObject(), EasyMock.anyObject(), EasyMock.anyObject());
EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
@Override
public Object answer() throws Throwable {
@SuppressWarnings("unchecked") Callback<Long> callback = (Callback<Long>) EasyMock.getCurrentArguments()[2];
callback.onError(new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR));
return null;
}
});
checkInvocation(asyncStatusResource, new RequestContext(), methodDescriptor, "POST", version, "/asyncstatuses/?action=streamingAction", payload, null, new Callback<RestResponse>() {
@Override
public void onError(Throwable e) {
}
@Override
public void onSuccess(RestResponse result) {
Assert.fail("Request passed unexpectedly.");
}
}, false, false, new RestLiAttachmentReader(null), new RestLiResponseAttachments.Builder().build());
// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Promise Method Execution - Successful scenario
methodDescriptor = promiseStatusResourceModel.findActionMethod("streamingAction", ResourceLevel.COLLECTION);
promiseStatusResource = getMockResource(PromiseStatusCollectionResource.class);
promiseStatusResource.streamingAction(EasyMock.anyObject(), EasyMock.anyObject());
EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
@Override
public Object answer() throws Throwable {
final SettablePromise<Long> result = Promises.settable();
final Runnable requestHandler = new Runnable() {
public void run() {
try {
result.done(1234l);
} catch (final Throwable throwable) {
result.fail(throwable);
}
}
};
_scheduler.schedule(requestHandler, 0, TimeUnit.MILLISECONDS);
return result;
}
});
checkInvocation(promiseStatusResource, new RequestContext(), methodDescriptor, "POST", version, "/promisestatuses/?action=streamingAction", payload, null, new Callback<RestResponse>() {
@Override
public void onError(Throwable e) {
Assert.fail("Request failed unexpectedly.");
}
@Override
public void onSuccess(RestResponse result) {
}
}, false, false, new RestLiAttachmentReader(null), new RestLiResponseAttachments.Builder().build());
// Promise Method Execution - Error scenario
promiseStatusResource = getMockResource(PromiseStatusCollectionResource.class);
promiseStatusResource.streamingAction(EasyMock.anyObject(), EasyMock.anyObject());
EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
@Override
public Object answer() throws Throwable {
final SettablePromise<Long> result = Promises.settable();
final Runnable requestHandler = new Runnable() {
public void run() {
result.fail(new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR));
}
};
_scheduler.schedule(requestHandler, 0, TimeUnit.MILLISECONDS);
return result;
}
});
checkInvocation(promiseStatusResource, new RequestContext(), methodDescriptor, "POST", version, "/promisestatuses/?action=streamingAction", payload, null, new Callback<RestResponse>() {
@Override
public void onError(Throwable e) {
}
@Override
public void onSuccess(RestResponse result) {
Assert.fail("Request passed unexpectedly.");
}
}, false, false, new RestLiAttachmentReader(null), new RestLiResponseAttachments.Builder().build());
// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Task Method Execution - Successful scenario
methodDescriptor = taskStatusResourceModel.findMethod(ResourceMethod.ACTION);
taskStatusResource = getMockResource(TaskStatusCollectionResource.class);
taskStatusResource.streamingAction(EasyMock.anyObject(), EasyMock.anyObject());
EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
@Override
public Object answer() throws Throwable {
return new BaseTask<Long>() {
protected Promise<Long> run(final Context context) throws Exception {
return Promises.value(1234l);
}
};
}
});
checkInvocation(taskStatusResource, new RequestContext(), methodDescriptor, "POST", version, "/taskstatuses/?action=streamingAction", payload, null, new Callback<RestResponse>() {
@Override
public void onError(Throwable e) {
Assert.fail("Request failed unexpectedly.");
}
@Override
public void onSuccess(RestResponse result) {
}
}, false, false, new RestLiAttachmentReader(null), new RestLiResponseAttachments.Builder().build());
// Task Method Execution - Error scenario
taskStatusResource = getMockResource(TaskStatusCollectionResource.class);
taskStatusResource.streamingAction(EasyMock.anyObject(), EasyMock.anyObject());
EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
@Override
public Object answer() throws Throwable {
return new BaseTask<Long>() {
protected Promise<Long> run(final Context context) throws Exception {
return Promises.error(new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR));
}
};
}
});
checkInvocation(taskStatusResource, new RequestContext(), methodDescriptor, "POST", version, "/taskstatuses/?action=streamingAction", payload, null, new Callback<RestResponse>() {
@Override
public void onError(Throwable e) {
}
@Override
public void onSuccess(RestResponse result) {
Assert.fail("Request passed unexpectedly.");
}
}, false, false, new RestLiAttachmentReader(null), new RestLiResponseAttachments.Builder().build());
}
use of com.linkedin.restli.common.attachments.RestLiAttachmentReader in project rest.li by linkedin.
the class TestRestLiMethodInvocation method testInvokeWithUnsupportedAcceptMimeType.
@Test
public void testInvokeWithUnsupportedAcceptMimeType() throws Exception {
RestRequestBuilder builder = new RestRequestBuilder(new URI("")).addHeaderValue("Accept", "text/plain").setHeader(RestConstants.HEADER_RESTLI_PROTOCOL_VERSION, version.toString());
RestRequest request = builder.build();
final RestLiAttachmentReader attachmentReader = new RestLiAttachmentReader(null);
final CountDownLatch latch = new CountDownLatch(1);
RestLiResponseHandler restLiResponseHandler = new RestLiResponseHandler(_methodAdapterProvider, _errorResponseBuilder);
ServerResourceContext resourceContext = new ResourceContextImpl(new PathKeysImpl(), new RestRequestBuilder(URI.create("")).setHeader(RestConstants.HEADER_RESTLI_PROTOCOL_VERSION, AllProtocolVersions.LATEST_PROTOCOL_VERSION.toString()).build(), new RequestContext());
resourceContext.setRequestAttachmentReader(attachmentReader);
Callback<RestLiResponse> executionCallback = new Callback<RestLiResponse>() {
@Override
public void onError(Throwable e) {
latch.countDown();
Assert.assertTrue(e instanceof RestException);
RestException ex = (RestException) e;
Assert.assertEquals(ex.getResponse().getStatus(), HttpStatus.S_406_NOT_ACCEPTABLE.getCode());
Assert.assertEquals(resourceContext.getRequestAttachmentReader(), attachmentReader);
Assert.assertNull(resourceContext.getResponseAttachments());
}
@Override
public void onSuccess(RestLiResponse result) {
Assert.fail();
}
};
try {
RoutingResult routingResult = new RoutingResult(resourceContext, null);
RestUtils.validateRequestHeadersAndUpdateResourceContext(request.getHeaders(), Collections.emptySet(), routingResult.getContext());
FilterChainDispatcher filterChainDispatcher = new FilterChainDispatcherImpl(routingResult, _invoker, null);
FilterChainCallback filterChainCallback = new FilterChainCallbackImpl(null, restLiResponseHandler, executionCallback, _errorResponseBuilder);
final RestLiCallback callback = new RestLiCallback(null, new RestLiFilterResponseContextFactory(request, null, restLiResponseHandler), new RestLiFilterChain(null, filterChainDispatcher, filterChainCallback));
_invoker.invoke(null, routingResult, null, callback);
latch.await();
} catch (Exception e) {
// exception is expected
Assert.assertTrue(e instanceof RestLiServiceException);
}
Assert.assertNull(resourceContext.getResponseMimeType());
}
use of com.linkedin.restli.common.attachments.RestLiAttachmentReader in project rest.li by linkedin.
the class ParseqTraceDebugRequestHandler method handleRequest.
@Override
public void handleRequest(final RestRequest request, final RequestContext context, final ResourceDebugRequestHandler resourceDebugRequestHandler, final RestLiAttachmentReader attachmentReader, final RequestExecutionCallback<RestResponse> callback) {
//Find out the path coming after the "__debug" path segment
String fullPath = request.getURI().getPath();
int debugSegmentIndex = fullPath.indexOf(RestLiServer.DEBUG_PATH_SEGMENT);
final String debugHandlerPath = fullPath.substring(debugSegmentIndex + RestLiServer.DEBUG_PATH_SEGMENT.length() + 1);
assert (debugHandlerPath.startsWith(HANDLER_ID));
//Decide whether this is a user issued debug request or a follow up static content request for tracevis html.
if (debugHandlerPath.equals(TRACEVIS_PATH) || debugHandlerPath.equals(RAW_PATH)) {
//Execute the request as if it was a regular rest.li request through resource debug request handler.
//By using the returned execution report shape the response accordingly.
//Since we are executing the request as though its a normal rest.li request, we don't have to
//drain the incoming request attachments. Our concerns are only the scenarios listed in the onError() and onSuccess()
//in the callback.
resourceDebugRequestHandler.handleRequest(request, context, new RequestExecutionCallback<RestResponse>() {
@Override
public void onError(Throwable e, RequestExecutionReport executionReport, RestLiAttachmentReader requestAttachmentReader, RestLiResponseAttachments responseAttachments) {
//this is sent back as a success so we handle it here instead.
if (requestAttachmentReader != null && !requestAttachmentReader.haveAllAttachmentsFinished()) {
try {
//Here we simply call drainAllAttachments. At this point the current callback assigned is likely the
//TopLevelReaderCallback in RestLiServer. When this callback is notified that draining is completed (via
//onDrainComplete()), then no action is taken (which is what is desired).
//
//We can go ahead and send the error back to the client while we continue to drain the
//bytes in the background. Note that it could be the case that even though there is an exception thrown,
//that application code could still be reading these attachments. In such a case we would not be able to call
//drainAllAttachments() successfully. Therefore we handle this exception and swallow.
requestAttachmentReader.drainAllAttachments();
} catch (RestLiAttachmentReaderException readerException) {
//Swallow here.
//It could be the case that the application code is still absorbing attachments.
//We back off and send the original response to the client. If the application code is not doing this,
//there is a chance for a resource leak. In such a case the framework can do nothing else.
}
}
//Drop all attachments to send back on the ground as well.
if (responseAttachments != null) {
responseAttachments.getResponseAttachmentsBuilder().build().abortAllDataSources(e);
}
sendDebugResponse(callback, executionReport, debugHandlerPath);
}
@Override
public void onSuccess(RestResponse result, RequestExecutionReport executionReport, RestLiResponseAttachments responseAttachments) {
//to drain them here.
if (responseAttachments != null) {
responseAttachments.getResponseAttachmentsBuilder().build().abortAllDataSources(new UnsupportedOperationException("Response attachments " + "may not be sent back for parseq trace debugging"));
}
sendDebugResponse(callback, executionReport, debugHandlerPath);
}
});
} else {
//We know that the request is a static content request. So here we figure out the internal path for the
//JAR resource from the request path. A request uri such as "/__debug/parseqtrace/trace.html" translates to
//"/tracevis/trace.html" for the resource path.
String resourcePath = debugHandlerPath.replaceFirst(HANDLER_ID, ENTRY_PATH_SEGMENT_TRACEVIS);
ClassLoader currentClassLoader = getClass().getClassLoader();
InputStream resourceStream = currentClassLoader.getResourceAsStream(resourcePath);
String mediaType = null;
if (resourceStream != null) {
mediaType = determineMediaType(resourcePath);
}
// If the requested file type is not supported by this debug request handler, return 404.
if (mediaType == null) {
callback.onError(new RestLiServiceException(HttpStatus.S_404_NOT_FOUND), null, null, null);
}
try {
sendByteArrayAsResponse(callback, IOUtils.toByteArray(resourceStream), mediaType);
} catch (IOException exception) {
callback.onError(new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, exception), null, null, null);
}
}
}
Aggregations