use of com.github.ambry.rest.RestResponseChannel in project ambry by linkedin.
the class PostAccountsHandlerTest method validRequestsTest.
/**
* Test valid request cases.
* @throws Exception
*/
@Test
public void validRequestsTest() throws Exception {
ThrowingConsumer<Collection<Account>> testAction = accountsToUpdate -> {
String requestBody = new String(AccountCollectionSerde.serializeAccountsInJson(accountsToUpdate));
RestResponseChannel restResponseChannel = new MockRestResponseChannel();
sendRequestGetResponse(requestBody, restResponseChannel);
assertNotNull("Date has not been set", restResponseChannel.getHeader(RestUtils.Headers.DATE));
assertEquals("Content-length is not as expected", 0, Integer.parseInt((String) restResponseChannel.getHeader(RestUtils.Headers.CONTENT_LENGTH)));
for (Account account : accountsToUpdate) {
assertEquals("Account in account service not as expected", account, accountService.getAccountById(account.getId()));
}
};
testAction.accept(Collections.emptyList());
// add new account
testAction.accept(Collections.singleton(accountService.generateRandomAccount()));
// update multiple accounts
testAction.accept(IntStream.range(0, 3).mapToObj(i -> {
Account account = accountService.createAndAddRandomAccount();
return new AccountBuilder(account).name(account.getName() + i).build();
}).collect(Collectors.toList()));
}
use of com.github.ambry.rest.RestResponseChannel in project ambry by linkedin.
the class FrontendRestRequestService method handleGet.
@Override
public void handleGet(final RestRequest restRequest, final RestResponseChannel restResponseChannel) {
ThrowingConsumer<RequestPath> routingAction = requestPath -> {
if (requestPath.matchesOperation(Operations.GET_PEERS)) {
getPeersHandler.handle(restRequest, restResponseChannel, (result, exception) -> submitResponse(restRequest, restResponseChannel, result, exception));
} else if (requestPath.matchesOperation(Operations.GET_CLUSTER_MAP_SNAPSHOT)) {
getClusterMapSnapshotHandler.handle(restRequest, restResponseChannel, (result, exception) -> submitResponse(restRequest, restResponseChannel, result, exception));
} else if (requestPath.matchesOperation(Operations.GET_SIGNED_URL)) {
getSignedUrlHandler.handle(restRequest, restResponseChannel, (result, exception) -> submitResponse(restRequest, restResponseChannel, result, exception));
} else if (requestPath.matchesOperation(Operations.ACCOUNTS)) {
getAccountsHandler.handle(restRequest, restResponseChannel, (result, exception) -> submitResponse(restRequest, restResponseChannel, result, exception));
} else if (requestPath.matchesOperation(Operations.STATS_REPORT)) {
getStatsReportHandler.handle(restRequest, restResponseChannel, (result, exception) -> submitResponse(restRequest, restResponseChannel, result, exception));
} else if (requestPath.matchesOperation(Operations.NAMED_BLOB) && NamedBlobPath.parse(requestPath, restRequest.getArgs()).getBlobName() == null) {
listNamedBlobsHandler.handle(restRequest, restResponseChannel, ((result, exception) -> submitResponse(restRequest, restResponseChannel, result, exception)));
} else {
SubResource subResource = requestPath.getSubResource();
GetBlobOptions options = buildGetBlobOptions(restRequest.getArgs(), subResource, getGetOption(restRequest, frontendConfig.defaultRouterGetOption), restRequest, requestPath.getBlobSegmentIdx());
GetCallback routerCallback = new GetCallback(restRequest, restResponseChannel, subResource, options);
SecurityProcessRequestCallback securityCallback = new SecurityProcessRequestCallback(restRequest, restResponseChannel, routerCallback);
if (subResource == SubResource.Replicas) {
securityCallback = new SecurityProcessRequestCallback(restRequest, restResponseChannel);
}
RestRequestMetricsGroup metricsGroup = getMetricsGroupForGet(frontendMetrics, subResource);
RestRequestMetrics restRequestMetrics = metricsGroup.getRestRequestMetrics(restRequest.isSslUsed(), false);
restRequest.getMetricsTracker().injectMetrics(restRequestMetrics);
// named blob requests have their account/container in the URI, so checks can be done prior to ID conversion.
if (requestPath.matchesOperation(Operations.NAMED_BLOB)) {
accountAndContainerInjector.injectAccountAndContainerForNamedBlob(restRequest, metricsGroup);
}
securityService.processRequest(restRequest, securityCallback);
}
};
preProcessAndRouteRequest(restRequest, restResponseChannel, frontendMetrics.getPreProcessingMetrics, routingAction);
}
use of com.github.ambry.rest.RestResponseChannel in project ambry by linkedin.
the class FrontendRestRequestService method securityPostProcessRequestCallback.
/**
* Build a callback to use for {@link SecurityService#postProcessRequest}. This callback forwards request to the
* {@link Router} once ID conversion is completed. In the case of some sub-resources
* (e.g., {@link SubResource#Replicas}), the request is completed and not forwarded to the {@link Router}.
* @param convertedId the converted blob ID to use in router requests.
* @param restRequest the {@link RestRequest}.
* @param restResponseChannel the {@link RestResponseChannel}.
* @param getCallback the {@link GetCallback} to use if this is a {@link RestMethod#GET} request, or null for other
* request types.
* @param headCallback the {@link HeadCallback} to use if this is a {@link RestMethod#HEAD} request, or null for other
* request types.
* @param deleteCallback the {@link DeleteCallback} to use if this is a {@link RestMethod#DELETE} request, or null for
* other request types.
* @return the {@link Callback} to use.
*/
private Callback<Void> securityPostProcessRequestCallback(String convertedId, RestRequest restRequest, RestResponseChannel restResponseChannel, GetCallback getCallback, HeadCallback headCallback, DeleteCallback deleteCallback) {
Callback<ReadableStreamChannel> completionCallback = (result, exception) -> submitResponse(restRequest, restResponseChannel, result, exception);
RestMethod restMethod = restRequest.getRestMethod();
AsyncOperationTracker.Metrics metrics;
switch(restMethod) {
case GET:
metrics = frontendMetrics.getSecurityPostProcessRequestMetrics;
break;
case HEAD:
metrics = frontendMetrics.headSecurityPostProcessRequestMetrics;
break;
case DELETE:
metrics = frontendMetrics.deleteSecurityPostProcessRequestMetrics;
break;
default:
throw new IllegalStateException("Unrecognized RestMethod: " + restMethod);
}
return FrontendUtils.buildCallback(metrics, result -> {
ReadableStreamChannel response = null;
switch(restMethod) {
case GET:
SubResource subResource = getRequestPath(restRequest).getSubResource();
// inject encryption metrics if need be
if (BlobId.isEncrypted(convertedId)) {
RestRequestMetrics restRequestMetrics = getMetricsGroupForGet(frontendMetrics, subResource).getRestRequestMetrics(restRequest.isSslUsed(), true);
restRequest.getMetricsTracker().injectMetrics(restRequestMetrics);
}
if (subResource == null) {
getCallback.markStartTime();
router.getBlob(convertedId, getCallback.options, getCallback, QuotaUtils.buildQuotaChargeCallback(restRequest, quotaManager, true));
} else {
switch(subResource) {
case BlobInfo:
case UserMetadata:
case Segment:
getCallback.markStartTime();
router.getBlob(convertedId, getCallback.options, getCallback, QuotaUtils.buildQuotaChargeCallback(restRequest, quotaManager, true));
break;
case Replicas:
response = getReplicasHandler.getReplicas(convertedId, restResponseChannel);
break;
}
}
break;
case HEAD:
GetOption getOption = getGetOption(restRequest, frontendConfig.defaultRouterGetOption);
// inject encryption metrics if need be
if (BlobId.isEncrypted(convertedId)) {
RestRequestMetrics requestMetrics = frontendMetrics.headBlobMetricsGroup.getRestRequestMetrics(restRequest.isSslUsed(), true);
restRequest.getMetricsTracker().injectMetrics(requestMetrics);
}
headCallback.markStartTime();
router.getBlob(convertedId, new GetBlobOptionsBuilder().operationType(GetBlobOptions.OperationType.BlobInfo).getOption(getOption).restRequest(restRequest).build(), headCallback, QuotaUtils.buildQuotaChargeCallback(restRequest, quotaManager, false));
break;
case DELETE:
deleteCallback.markStartTime();
router.deleteBlob(convertedId, getHeader(restRequest.getArgs(), Headers.SERVICE_ID, false), deleteCallback, QuotaUtils.buildQuotaChargeCallback(restRequest, quotaManager, false));
break;
default:
throw new IllegalStateException("Unrecognized RestMethod: " + restMethod);
}
if (response != null) {
completionCallback.onCompletion(response, null);
}
}, restRequest.getUri(), logger, completionCallback);
}
use of com.github.ambry.rest.RestResponseChannel in project ambry by linkedin.
the class GetStatsReportHandlerTest method handleGoodCaseTest.
@Test
public void handleGoodCaseTest() throws Exception {
AggregatedAccountStorageStats aggregatedAccountStorageStats = new AggregatedAccountStorageStats(StorageStatsUtilTest.generateRandomAggregatedAccountStorageStats((short) 1, 10, 10, 1000L, 2, 100));
doAnswer(invocation -> {
String clusterName = invocation.getArgument(0);
if (clusterName.equals(CLUSTER_NAME)) {
return aggregatedAccountStorageStats;
} else {
return null;
}
}).when(accountStatsStore).queryAggregatedAccountStorageStatsByClusterName(anyString());
RestRequest restRequest = createRestRequest(CLUSTER_NAME, StatsReportType.ACCOUNT_REPORT.name());
RestResponseChannel restResponseChannel = new MockRestResponseChannel();
ReadableStreamChannel channel = sendRequestGetResponse(restRequest, restResponseChannel);
assertNotNull("There should be a response", channel);
assertNotNull("Date has not been set", restResponseChannel.getHeader(RestUtils.Headers.DATE));
assertEquals("Content-type is not as expected", RestUtils.JSON_CONTENT_TYPE, restResponseChannel.getHeader(RestUtils.Headers.CONTENT_TYPE));
assertEquals("Content-length is not as expected", channel.getSize(), Integer.parseInt((String) restResponseChannel.getHeader(RestUtils.Headers.CONTENT_LENGTH)));
assertEquals("Storage stats mismatch", aggregatedAccountStorageStats.getStorageStats(), mapper.readValue(RestTestUtils.getResponseBody(channel), AggregatedAccountStorageStats.class).getStorageStats());
AggregatedPartitionClassStorageStats aggregatedPartitionClassStorageStats = new AggregatedPartitionClassStorageStats(StorageStatsUtilTest.generateRandomAggregatedPartitionClassStorageStats(new String[] { "default", "newClass" }, (short) 1, 10, 10, 1000L, 2, 100));
doAnswer(invocation -> {
String clusterName = invocation.getArgument(0);
if (clusterName.equals(CLUSTER_NAME)) {
return aggregatedPartitionClassStorageStats;
} else {
return null;
}
}).when(accountStatsStore).queryAggregatedPartitionClassStorageStatsByClusterName(anyString());
restRequest = createRestRequest(CLUSTER_NAME, StatsReportType.PARTITION_CLASS_REPORT.name());
restResponseChannel = new MockRestResponseChannel();
channel = sendRequestGetResponse(restRequest, restResponseChannel);
assertNotNull("There should be a response", channel);
assertNotNull("Date has not been set", restResponseChannel.getHeader(RestUtils.Headers.DATE));
assertEquals("Content-type is not as expected", RestUtils.JSON_CONTENT_TYPE, restResponseChannel.getHeader(RestUtils.Headers.CONTENT_TYPE));
assertEquals("Content-length is not as expected", channel.getSize(), Integer.parseInt((String) restResponseChannel.getHeader(RestUtils.Headers.CONTENT_LENGTH)));
assertEquals("Storage stats mismatch", aggregatedPartitionClassStorageStats.getStorageStats(), mapper.readValue(RestTestUtils.getResponseBody(channel), AggregatedPartitionClassStorageStats.class).getStorageStats());
}
use of com.github.ambry.rest.RestResponseChannel in project ambry by linkedin.
the class PostBlobHandlerTest method doTtlRequiredEnforcementTest.
// ttlRequiredEnforcementTest() helpers
/**
* Does the TTL required enforcement test by selecting the right verification methods based on container and frontend
* config
* @param container the {@link Container} to upload to
* @param blobTtlSecs the TTL to set for the blob
* @throws Exception
*/
private void doTtlRequiredEnforcementTest(Container container, long blobTtlSecs) throws Exception {
JSONObject headers = new JSONObject();
FrontendRestRequestServiceTest.setAmbryHeadersForPut(headers, blobTtlSecs, !container.isCacheable(), SERVICE_ID, CONTENT_TYPE, OWNER_ID, REF_ACCOUNT.getName(), container.getName(), null);
byte[] content = TestUtils.getRandomBytes(1024);
RestRequest request = getRestRequest(headers, "/", content);
RestResponseChannel restResponseChannel = new MockRestResponseChannel();
FutureResult<Void> future = new FutureResult<>();
postBlobHandler.handle(request, restResponseChannel, future::done);
if (container.isTtlRequired() && (blobTtlSecs == Utils.Infinite_Time || blobTtlSecs > frontendConfig.maxAcceptableTtlSecsIfTtlRequired)) {
if (frontendConfig.failIfTtlRequiredButNotProvided) {
try {
future.get(TIMEOUT_SECS, TimeUnit.SECONDS);
fail("Post should have failed");
} catch (ExecutionException e) {
RestServiceException rootCause = (RestServiceException) Utils.getRootCause(e);
assertNotNull("Root cause should be a RestServiceException", rootCause);
assertEquals("Incorrect RestServiceErrorCode", RestServiceErrorCode.InvalidArgs, rootCause.getErrorCode());
}
} else {
verifySuccessResponseOnTtlEnforcement(future, content, blobTtlSecs, restResponseChannel, true);
}
} else {
verifySuccessResponseOnTtlEnforcement(future, content, blobTtlSecs, restResponseChannel, false);
}
}
Aggregations