use of com.github.ambry.rest.RestMethod in project ambry by linkedin.
the class AmbryUrlSigningService method getSignedUrl.
@Override
public String getSignedUrl(RestRequest restRequest) throws RestServiceException {
Map<String, Object> args = restRequest.getArgs();
String restMethodInSignedUrlStr = RestUtils.getHeader(args, RestUtils.Headers.URL_TYPE, true);
RestMethod restMethodInSignedUrl;
try {
restMethodInSignedUrl = RestMethod.valueOf(restMethodInSignedUrlStr);
} catch (IllegalArgumentException e) {
throw new RestServiceException("Unrecognized RestMethod: " + restMethodInSignedUrlStr, RestServiceErrorCode.InvalidArgs);
}
StringBuilder urlBuilder = new StringBuilder();
switch(restMethodInSignedUrl) {
case GET:
urlBuilder.append(downloadEndpoint);
break;
case POST:
urlBuilder.append(uploadEndpoint);
break;
default:
throw new RestServiceException("Signing request for " + restMethodInSignedUrl + " is not supported", RestServiceErrorCode.InvalidArgs);
}
long urlTtlSecs = defaultUrlTtlSecs;
long maxUploadSize = defaultMaxUploadSize;
boolean chunkUpload = false;
Map<String, Object> argsForUrl = new HashMap<>();
for (Map.Entry<String, Object> entry : args.entrySet()) {
String name = entry.getKey();
Object value = entry.getValue();
if (name.regionMatches(true, 0, AMBRY_PARAMETERS_PREFIX, 0, AMBRY_PARAMETERS_PREFIX.length()) && value instanceof String) {
switch(name) {
case RestUtils.Headers.URL_TTL:
urlTtlSecs = Math.min(maxUrlTtlSecs, RestUtils.getLongHeader(args, RestUtils.Headers.URL_TTL, true));
break;
case RestUtils.Headers.MAX_UPLOAD_SIZE:
maxUploadSize = RestUtils.getLongHeader(args, RestUtils.Headers.MAX_UPLOAD_SIZE, true);
break;
case RestUtils.Headers.CHUNK_UPLOAD:
chunkUpload = RestUtils.getBooleanHeader(args, RestUtils.Headers.CHUNK_UPLOAD, true);
break;
default:
argsForUrl.put(name, value);
break;
}
}
}
if (RestMethod.POST.equals(restMethodInSignedUrl)) {
if (chunkUpload) {
// Chunks of a stitched blob have a fixed max size to ensure that the router does not do further chunking as
// this is not supported by the current metadata format.
maxUploadSize = chunkUploadMaxChunkSize;
// They also have a non-optional blob TTL to ensure that chunks that were not stitched within a reasonable time
// span are cleaned up.
argsForUrl.put(RestUtils.Headers.TTL, chunkUploadInitialChunkTtlSecs);
argsForUrl.put(RestUtils.Headers.CHUNK_UPLOAD, true);
argsForUrl.put(RestUtils.Headers.SESSION, UUID.randomUUID().toString());
}
argsForUrl.put(RestUtils.Headers.MAX_UPLOAD_SIZE, maxUploadSize);
}
argsForUrl.put(LINK_EXPIRY_TIME, time.seconds() + urlTtlSecs);
String nextSeparator = QUERY_STRING_START;
for (Map.Entry<String, Object> entry : argsForUrl.entrySet()) {
String value = urlEncode(entry.getValue());
urlBuilder.append(nextSeparator).append(entry.getKey()).append(PARAMETER_ASSIGN).append(value);
nextSeparator = PARAMETER_SEPARATOR;
}
return urlBuilder.toString();
}
use of com.github.ambry.rest.RestMethod in project ambry by linkedin.
the class AmbryUrlSigningService method verifySignedRequest.
@Override
public void verifySignedRequest(RestRequest restRequest) throws RestServiceException {
if (!isRequestSigned(restRequest)) {
throw new RestServiceException("Request is not signed - method should not have been called", RestServiceErrorCode.InternalServerError);
}
Map<String, Object> args = restRequest.getArgs();
long expiryTimeSecs = RestUtils.getLongHeader(args, LINK_EXPIRY_TIME, true);
if (time.seconds() > expiryTimeSecs) {
throw new RestServiceException("Signed URL has expired", RestServiceErrorCode.Unauthorized);
}
RestMethod restMethodInUrl = RestMethod.valueOf(RestUtils.getHeader(args, RestUtils.Headers.URL_TYPE, true));
if (!restRequest.getRestMethod().equals(restMethodInUrl)) {
throw new RestServiceException("Type of request being made not compatible with signed URL", RestServiceErrorCode.Unauthorized);
}
}
use of com.github.ambry.rest.RestMethod in project ambry by linkedin.
the class GetSignedUrlHandler method handle.
/**
* Handles a request for getting signed URLs.
* @param restRequest the {@link RestRequest} that contains the request parameters.
* @param restResponseChannel the {@link RestResponseChannel} where headers should be set.
* @param callback the {@link Callback} to invoke when the response is ready (or if there is an exception).
* @throws RestServiceException if required parameters are not found or are invalid
*/
void handle(RestRequest restRequest, RestResponseChannel restResponseChannel, Callback<ReadableStreamChannel> callback) throws RestServiceException {
RestRequestMetrics requestMetrics = metrics.getSignedUrlMetricsGroup.getRestRequestMetrics(restRequest.isSslUsed(), false);
restRequest.getMetricsTracker().injectMetrics(requestMetrics);
String restMethodInSignedUrlStr = RestUtils.getHeader(restRequest.getArgs(), RestUtils.Headers.URL_TYPE, true);
RestMethod restMethodInUrl;
try {
restMethodInUrl = RestMethod.valueOf(restMethodInSignedUrlStr);
} catch (IllegalArgumentException e) {
throw new RestServiceException("Unrecognized RestMethod: " + restMethodInSignedUrlStr, RestServiceErrorCode.InvalidArgs);
}
securityService.processRequest(restRequest, new SecurityProcessRequestCallback(restRequest, restMethodInUrl, restResponseChannel, callback));
}
use of com.github.ambry.rest.RestMethod in project ambry by linkedin.
the class FrontendTestUrlSigningServiceFactory method doExternalServicesBadInputTest.
/**
* Does the tests to check for exception pipelining for exceptions returned/thrown by external services.
* @param restMethods the {@link RestMethod} types for which the test has to be run.
* @param expectedExceptionMsg the expected exception message.
* @param expectRouterCall if the router should have returned a value before the exception occurs.
* @throws JSONException
*/
private void doExternalServicesBadInputTest(RestMethod[] restMethods, String expectedExceptionMsg, boolean expectRouterCall) throws JSONException {
for (RestMethod restMethod : restMethods) {
if (restMethod.equals(RestMethod.UNKNOWN)) {
continue;
}
JSONObject headers = new JSONObject();
List<ByteBuffer> contents = null;
if (restMethod.equals(RestMethod.POST)) {
setAmbryHeadersForPut(headers, 7200, !refContainer.isCacheable(), "doExternalServicesBadInputTest", "application/octet-stream", "doExternalServicesBadInputTest", refAccount.getName(), refContainer.getName(), null);
contents = new ArrayList<>(1);
contents.add(null);
}
String blobIdStr = new BlobId(blobIdVersion, BlobId.BlobIdType.NATIVE, (byte) -1, Account.UNKNOWN_ACCOUNT_ID, Container.UNKNOWN_CONTAINER_ID, clusterMap.getAllPartitionIds(null).get(0), false, BlobId.BlobDataType.DATACHUNK).getID();
try {
doOperation(createRestRequest(restMethod, blobIdStr, headers, contents), new MockRestResponseChannel());
fail("Operation " + restMethod + " should have failed because an external service would have thrown an exception");
} catch (Exception e) {
assertEquals("Unexpected exception message", expectedExceptionMsg, e.getMessage());
if (expectRouterCall && restMethod == RestMethod.GET) {
assertNotNull("expected router.getBlob() call to provide a response to responseHandler", responseHandler.getResponse());
}
}
}
}
use of com.github.ambry.rest.RestMethod in project ambry by linkedin.
the class FrontendTestUrlSigningServiceFactory method useServiceWithoutStartTest.
/**
* This tests for exceptions thrown when an {@link FrontendRestRequestService} instance is used without calling
* {@link FrontendRestRequestService#start()} first.
* @throws Exception
*/
@Test
public void useServiceWithoutStartTest() throws Exception {
frontendRestRequestService = getFrontendRestRequestService();
frontendRestRequestService.setupResponseHandler(responseHandler);
// not fine to use without start.
for (RestMethod method : RestMethod.values()) {
if (method.equals(RestMethod.UNKNOWN)) {
continue;
}
verifyOperationFailure(createRestRequest(method, "/", null, null), RestServiceErrorCode.ServiceUnavailable);
}
}
Aggregations