use of com.github.ambry.rest.RestServiceException in project ambry by linkedin.
the class AmbryBlobStorageService method handlePut.
@Override
public void handlePut(RestRequest restRequest, RestResponseChannel restResponseChannel) {
handlePrechecks(restRequest, restResponseChannel);
Exception exception = isUp ? new RestServiceException("PUT is not supported", RestServiceErrorCode.UnsupportedHttpMethod) : new RestServiceException("AmbryBlobStorageService unavailable", RestServiceErrorCode.ServiceUnavailable);
submitResponse(restRequest, restResponseChannel, null, exception);
}
use of com.github.ambry.rest.RestServiceException in project ambry by linkedin.
the class AmbrySecurityService method postProcessRequest.
@Override
public void postProcessRequest(RestRequest restRequest, Callback<Void> callback) {
Exception exception = null;
frontendMetrics.securityServicePostProcessRequestRate.mark();
long startTimeMs = System.currentTimeMillis();
if (!isOpen) {
exception = new RestServiceException("SecurityService is closed", RestServiceErrorCode.ServiceUnavailable);
} else if (restRequest == null || callback == null) {
throw new IllegalArgumentException("RestRequest or Callback is null");
}
// check preconditions for DELETE request
if (restRequest.getRestMethod() == RestMethod.DELETE) {
try {
accountAndContainerNamePreconditionCheck(restRequest);
} catch (Exception e) {
exception = e;
}
}
frontendMetrics.securityServicePostProcessRequestTimeInMs.update(System.currentTimeMillis() - startTimeMs);
callback.onCompletion(null, exception);
}
use of com.github.ambry.rest.RestServiceException in project ambry by linkedin.
the class AmbrySecurityService method processResponse.
@Override
public void processResponse(RestRequest restRequest, RestResponseChannel responseChannel, BlobInfo blobInfo, Callback<Void> callback) {
Exception exception = null;
frontendMetrics.securityServiceProcessResponseRate.mark();
long startTimeMs = System.currentTimeMillis();
if (!isOpen) {
exception = new RestServiceException("SecurityService is closed", RestServiceErrorCode.ServiceUnavailable);
} else {
if (restRequest == null || responseChannel == null) {
throw new IllegalArgumentException("One of the required params is null");
}
String operationOrBlobId = RestUtils.getOperationOrBlobIdFromUri(restRequest, RestUtils.getBlobSubResource(restRequest), frontendConfig.frontendPathPrefixesToRemove);
if (operationOrBlobId.startsWith("/")) {
operationOrBlobId = operationOrBlobId.substring(1);
}
if (blobInfo == null && !restRequest.getRestMethod().equals(RestMethod.OPTIONS)) {
if (!operationOrBlobId.equals(Operations.GET_SIGNED_URL)) {
throw new IllegalArgumentException("BlobInfo is null");
}
}
try {
GetBlobOptions options;
responseChannel.setHeader(RestUtils.Headers.DATE, new GregorianCalendar().getTime());
RestMethod restMethod = restRequest.getRestMethod();
switch(restMethod) {
case HEAD:
options = RestUtils.buildGetBlobOptions(restRequest.getArgs(), null, GetOption.None);
responseChannel.setStatus(options.getRange() == null ? ResponseStatus.Ok : ResponseStatus.PartialContent);
responseChannel.setHeader(RestUtils.Headers.LAST_MODIFIED, new Date(blobInfo.getBlobProperties().getCreationTimeInMs()));
setHeadResponseHeaders(blobInfo, options, restRequest, responseChannel);
break;
case GET:
if (!operationOrBlobId.equals(Operations.GET_SIGNED_URL)) {
responseChannel.setStatus(ResponseStatus.Ok);
RestUtils.SubResource subResource = RestUtils.getBlobSubResource(restRequest);
responseChannel.setHeader(RestUtils.Headers.LAST_MODIFIED, new Date(blobInfo.getBlobProperties().getCreationTimeInMs()));
if (subResource == null) {
Long ifModifiedSinceMs = getIfModifiedSinceMs(restRequest);
if (ifModifiedSinceMs != null && RestUtils.toSecondsPrecisionInMs(blobInfo.getBlobProperties().getCreationTimeInMs()) <= ifModifiedSinceMs) {
responseChannel.setStatus(ResponseStatus.NotModified);
} else {
options = RestUtils.buildGetBlobOptions(restRequest.getArgs(), null, GetOption.None);
if (options.getRange() != null) {
responseChannel.setStatus(ResponseStatus.PartialContent);
}
setGetBlobResponseHeaders(blobInfo, options, responseChannel);
}
setCacheHeaders(restRequest, responseChannel);
} else {
if (subResource.equals(RestUtils.SubResource.BlobInfo)) {
setBlobPropertiesHeaders(blobInfo.getBlobProperties(), responseChannel);
setAccountAndContainerHeaders(restRequest, responseChannel);
}
}
}
break;
case POST:
responseChannel.setStatus(ResponseStatus.Created);
responseChannel.setHeader(RestUtils.Headers.CONTENT_LENGTH, 0);
responseChannel.setHeader(RestUtils.Headers.CREATION_TIME, new Date(blobInfo.getBlobProperties().getCreationTimeInMs()));
break;
case OPTIONS:
break;
default:
exception = new RestServiceException("Cannot process response for request with method " + restMethod, RestServiceErrorCode.InternalServerError);
}
} catch (RestServiceException e) {
exception = e;
}
}
frontendMetrics.securityServiceProcessResponseTimeInMs.update(System.currentTimeMillis() - startTimeMs);
callback.onCompletion(null, exception);
}
use of com.github.ambry.rest.RestServiceException in project ambry by linkedin.
the class FrontendTestUrlSigningServiceFactory method getAndUseSignedUrlTest.
/**
* Tests the handling of {@link Operations#GET_SIGNED_URL} requests.
* @throws Exception
*/
@Test
public void getAndUseSignedUrlTest() throws Exception {
// setup
int contentLength = 10;
ByteBuffer content = ByteBuffer.wrap(TestUtils.getRandomBytes(contentLength));
long blobTtl = 7200;
String serviceId = "getAndUseSignedUrlTest";
String contentType = "application/octet-stream";
String ownerId = "getAndUseSignedUrlTest";
JSONObject headers = new JSONObject();
headers.put(RestUtils.Headers.URL_TYPE, RestMethod.POST.name());
setAmbryHeadersForPut(headers, blobTtl, !refContainer.isCacheable(), serviceId, contentType, ownerId, refAccount.getName(), refContainer.getName());
Map<String, String> userMetadata = new HashMap<>();
userMetadata.put(RestUtils.Headers.USER_META_DATA_HEADER_PREFIX + "key1", "value1");
userMetadata.put(RestUtils.Headers.USER_META_DATA_HEADER_PREFIX + "key2", "value2");
RestUtilsTest.setUserMetadataHeaders(headers, userMetadata);
// POST
// Get signed URL
RestRequest getSignedUrlRequest = createRestRequest(RestMethod.GET, Operations.GET_SIGNED_URL, headers, null);
MockRestResponseChannel restResponseChannel = new MockRestResponseChannel();
doOperation(getSignedUrlRequest, restResponseChannel);
assertEquals("Account not as expected", refAccount, getSignedUrlRequest.getArgs().get(RestUtils.InternalKeys.TARGET_ACCOUNT_KEY));
assertEquals("Container not as expected", refContainer, getSignedUrlRequest.getArgs().get(RestUtils.InternalKeys.TARGET_CONTAINER_KEY));
assertEquals("Unexpected response status", ResponseStatus.Ok, restResponseChannel.getStatus());
String signedPostUrl = restResponseChannel.getHeader(RestUtils.Headers.SIGNED_URL);
assertNotNull("Did not get a signed POST URL", signedPostUrl);
// Use signed URL to POST
List<ByteBuffer> contents = new LinkedList<>();
contents.add(content);
contents.add(null);
RestRequest postSignedRequest = createRestRequest(RestMethod.POST, signedPostUrl, null, contents);
restResponseChannel = new MockRestResponseChannel();
doOperation(postSignedRequest, restResponseChannel);
String blobId = verifyPostAndReturnBlobId(postSignedRequest, restResponseChannel, refAccount, refContainer);
// verify POST
headers.put(RestUtils.Headers.BLOB_SIZE, contentLength);
getBlobAndVerify(blobId, null, null, headers, content, refAccount, refContainer);
getBlobInfoAndVerify(blobId, null, headers, refAccount, refContainer);
// GET
// Get signed URL
JSONObject getHeaders = new JSONObject();
getHeaders.put(RestUtils.Headers.URL_TYPE, RestMethod.GET.name());
blobId = blobId.startsWith("/") ? blobId.substring(1) : blobId;
getHeaders.put(RestUtils.Headers.BLOB_ID, blobId);
getSignedUrlRequest = createRestRequest(RestMethod.GET, Operations.GET_SIGNED_URL, getHeaders, null);
restResponseChannel = new MockRestResponseChannel();
doOperation(getSignedUrlRequest, restResponseChannel);
assertEquals("Account not as expected", refAccount, getSignedUrlRequest.getArgs().get(RestUtils.InternalKeys.TARGET_ACCOUNT_KEY));
assertEquals("Container not as expected", refContainer, getSignedUrlRequest.getArgs().get(RestUtils.InternalKeys.TARGET_CONTAINER_KEY));
assertEquals("Unexpected response status", ResponseStatus.Ok, restResponseChannel.getStatus());
String signedGetUrl = restResponseChannel.getHeader(RestUtils.Headers.SIGNED_URL);
assertNotNull("Did not get a signed GET URL", signedGetUrl);
// Use URL to GET blob
RestRequest getSignedRequest = createRestRequest(RestMethod.GET, signedGetUrl, null, null);
restResponseChannel = new MockRestResponseChannel();
doOperation(getSignedRequest, restResponseChannel);
verifyGetBlobResponse(getSignedRequest, restResponseChannel, null, headers, content, refAccount, refContainer);
// one error scenario to exercise exception path
try {
doOperation(createRestRequest(RestMethod.GET, Operations.GET_SIGNED_URL, null, null), new MockRestResponseChannel());
fail("Operation should have failed because some necessary parameters are missing");
} catch (RestServiceException e) {
assertEquals("RestServiceErrorCode not as expected", RestServiceErrorCode.MissingArgs, e.getErrorCode());
}
}
use of com.github.ambry.rest.RestServiceException in project ambry by linkedin.
the class FrontendTestUrlSigningServiceFactory method doConditionalDeleteTest.
/**
* Tests blob conditional DELETE operations on the given {@code container}.
* @param toPostAccount the {@link Account} to use in post headers. Can be {@code null} if only using service ID.
* @param toPostContainer the {@link Container} to use in post headers. Can be {@code null} if only using service ID.
* @param serviceId the serviceId to use for the POST
* @param isPrivate the isPrivate flag to pass as part of the POST
* @param expectedAccount the {@link Account} details that are eventually expected to be populated.
* @param expectedContainer the {@link Container} details that are eventually expected to be populated.
* @throws Exception
*/
private void doConditionalDeleteTest(Account toPostAccount, Container toPostContainer, String serviceId, boolean isPrivate, Account expectedAccount, Container expectedContainer) throws Exception {
final int CONTENT_LENGTH = 1024;
ByteBuffer content = ByteBuffer.wrap(TestUtils.getRandomBytes(CONTENT_LENGTH));
String contentType = "application/octet-stream";
String ownerId = "postGetHeadDeleteOwnerID";
JSONObject headers = new JSONObject();
String accountNameInPost = toPostAccount != null ? toPostAccount.getName() : null;
String containerNameInPost = toPostContainer != null ? toPostContainer.getName() : null;
setAmbryHeadersForPut(headers, 7200, isPrivate, serviceId, contentType, ownerId, accountNameInPost, containerNameInPost);
Map<String, String> userMetadata = new HashMap<>();
userMetadata.put(RestUtils.Headers.USER_META_DATA_HEADER_PREFIX + "key1", "value1");
userMetadata.put(RestUtils.Headers.USER_META_DATA_HEADER_PREFIX + "key2", "value2");
RestUtilsTest.setUserMetadataHeaders(headers, userMetadata);
// perform POST, GET, HEAD successfully before DELETE
String blobId = postBlobAndVerify(headers, content, expectedAccount, expectedContainer);
headers.put(RestUtils.Headers.BLOB_SIZE, (long) CONTENT_LENGTH);
getBlobAndVerify(blobId, null, null, headers, content, expectedAccount, expectedContainer);
getHeadAndVerify(blobId, null, null, headers, expectedAccount, expectedContainer);
// test Conditional Delete failure because only container name is set
RestResponseChannel restResponseChannel = new MockRestResponseChannel();
JSONObject headers2 = new JSONObject();
setAccountAndContainerHeaders(headers2, null, containerNameInPost);
RestRequest restRequest = createRestRequest(RestMethod.DELETE, blobId, headers2, null);
try {
doOperation(restRequest, restResponseChannel);
fail("Operation should have failed because only container name is set");
} catch (RestServiceException e) {
assertEquals("AmbryBlobStorageService should have thrown a BadRequest exception", RestServiceErrorCode.BadRequest, e.getErrorCode());
}
// test Conditional Delete failure because of incorrect account name
restResponseChannel = new MockRestResponseChannel();
setAccountAndContainerHeaders(headers, "INCORRECT_ACCOUNT_NAME", containerNameInPost);
restRequest = createRestRequest(RestMethod.DELETE, blobId, headers, null);
try {
doOperation(restRequest, restResponseChannel);
fail("Operation should have failed because incorrect account name");
} catch (RestServiceException e) {
assertEquals("AmbryBlobStorageService should have thrown a PreconditionFailed exception", RestServiceErrorCode.PreconditionFailed, e.getErrorCode());
}
// test Conditional Delete failure because of incorrect container name
restResponseChannel = new MockRestResponseChannel();
setAccountAndContainerHeaders(headers, accountNameInPost, "INCORRECT_CONTAINER_NAME");
restRequest = createRestRequest(RestMethod.DELETE, blobId, headers, null);
try {
doOperation(restRequest, restResponseChannel);
fail("Operation should have failed because incorrect container name");
} catch (RestServiceException e) {
assertEquals("AmbryBlobStorageService should have thrown a PreconditionFailed exception", RestServiceErrorCode.PreconditionFailed, e.getErrorCode());
}
// test Conditional Delete succeeds
setAccountAndContainerHeaders(headers, accountNameInPost, containerNameInPost);
restRequest = createRestRequest(RestMethod.DELETE, blobId, headers, null);
verifyDeleteAccepted(restRequest);
// check GET, HEAD and DELETE after delete.
verifyOperationsAfterDelete(blobId, headers, content, expectedAccount, expectedContainer);
}
Aggregations