use of com.linkedin.restli.server.RoutingException in project rest.li by linkedin.
the class RestLiRouter method parseSimpleKey.
private static void parseSimpleKey(final ResourceModel resource, final ServerResourceContext context, final String pathSegment) {
Object parsedKey;
try {
parsedKey = ArgumentUtils.parseSimplePathKey(pathSegment, resource, context.getRestliProtocolVersion());
} catch (NumberFormatException e) {
// thrown from Integer.valueOf or Long.valueOf
throw new RoutingException(String.format("Key value '%s' must be of type '%s'", pathSegment, resource.getKeyClass().getName()), HttpStatus.S_400_BAD_REQUEST.getCode(), e);
} catch (IllegalArgumentException e) {
// thrown from Enum.valueOf
throw new RoutingException(String.format("Key parameter value '%s' is invalid", pathSegment), HttpStatus.S_400_BAD_REQUEST.getCode(), e);
} catch (TemplateRuntimeException e) {
// thrown from DateTemplateUtil.coerceOutput
throw new RoutingException(String.format("Key parameter value '%s' is invalid", pathSegment), HttpStatus.S_400_BAD_REQUEST.getCode(), e);
}
context.getPathKeys().append(resource.getKeyName(), parsedKey);
}
use of com.linkedin.restli.server.RoutingException in project rest.li by linkedin.
the class RestLiRouter method process.
/**
* Processes provided {@link RestRequest}.
*
* @param req {@link RestRequest}
* @return {@link RoutingResult}
*/
public RoutingResult process(final RestRequest req, final RequestContext requestContext, final RestLiAttachmentReader attachmentReader) {
String path = req.getURI().getRawPath();
if (path.length() < 2) {
throw new RoutingException(HttpStatus.S_404_NOT_FOUND.getCode());
}
if (path.charAt(0) == '/') {
path = path.substring(1);
}
Queue<String> remainingPath = new LinkedList<String>(Arrays.asList(SLASH_PATTERN.split(path)));
String rootPath = "/" + remainingPath.poll();
ResourceModel currentResource;
try {
currentResource = _pathRootResourceMap.get(URLDecoder.decode(rootPath, RestConstants.DEFAULT_CHARSET_NAME));
} catch (UnsupportedEncodingException e) {
throw new RestLiInternalException("UnsupportedEncodingException while trying to decode the root path", e);
}
if (currentResource == null) {
throw new RoutingException(String.format("No root resource defined for path '%s'", rootPath), HttpStatus.S_404_NOT_FOUND.getCode());
}
ServerResourceContext context;
try {
final String acceptTypeHeader = req.getHeader(RestConstants.HEADER_ACCEPT);
boolean responseAttachmentsAllowed = false;
if (acceptTypeHeader != null) {
final List<String> acceptTypes = MIMEParse.parseAcceptType(acceptTypeHeader);
for (final String acceptType : acceptTypes) {
if (acceptType.equalsIgnoreCase(RestConstants.HEADER_VALUE_MULTIPART_RELATED)) {
responseAttachmentsAllowed = true;
}
}
}
context = new ResourceContextImpl(new PathKeysImpl(), req, requestContext, responseAttachmentsAllowed, attachmentReader);
} catch (RestLiSyntaxException e) {
throw new RoutingException(e.getMessage(), HttpStatus.S_400_BAD_REQUEST.getCode());
}
return processResourceTree(currentResource, context, remainingPath);
}
use of com.linkedin.restli.server.RoutingException in project rest.li by linkedin.
the class RestLiRouter method parseComplexKey.
/**
* Instantiate the complex key from the current path segment (treat is as a list of
* query parameters) and put it into the context.
*
* @param currentPathSegment
* @param context
* @param resource
* @return
*/
private static void parseComplexKey(final ResourceModel resource, final ServerResourceContext context, final String currentPathSegment) {
try {
ComplexKeySpec<? extends RecordTemplate, ? extends RecordTemplate> complexKeyType = ComplexKeySpec.forClassesMaybeNull(resource.getKeyKeyClass(), resource.getKeyParamsClass());
ComplexResourceKey<RecordTemplate, RecordTemplate> complexKey = ComplexResourceKey.parseString(currentPathSegment, complexKeyType, context.getRestliProtocolVersion());
context.getPathKeys().append(resource.getKeyName(), complexKey);
} catch (PathSegmentSyntaxException e) {
throw new RoutingException(String.format("Complex key query parameters parsing error: '%s'", e.getMessage()), HttpStatus.S_400_BAD_REQUEST.getCode());
}
}
use of com.linkedin.restli.server.RoutingException in project rest.li by linkedin.
the class RestLiRouter method findMethodDescriptor.
private RoutingResult findMethodDescriptor(final ResourceModel resource, final ResourceLevel resourceLevel, final ServerResourceContext context) {
ResourceMethod type = mapResourceMethod(context, resourceLevel);
String methodName = context.getRequestActionName();
if (methodName == null) {
methodName = context.getRequestFinderName();
}
ResourceMethodDescriptor methodDescriptor = resource.matchMethod(type, methodName, resourceLevel);
if (methodDescriptor != null) {
context.getRawRequestContext().putLocalAttr(R2Constants.OPERATION, OperationNameGenerator.generate(methodDescriptor.getMethodType(), methodName));
return new RoutingResult(context, methodDescriptor);
}
String httpMethod = context.getRequestMethod();
if (methodName != null) {
throw new RoutingException(String.format("%s operation " + "named %s " + "not supported on resource '%s' " + "URI: '%s'", httpMethod, methodName, resource.getResourceClass().getName(), context.getRequestURI().toString()), HttpStatus.S_400_BAD_REQUEST.getCode());
}
throw new RoutingException(String.format("%s operation not supported " + "for URI: '%s' " + "with " + RestConstants.HEADER_RESTLI_REQUEST_METHOD + ": '%s'", httpMethod, context.getRequestURI().toString(), context.getRestLiRequestMethod()), HttpStatus.S_400_BAD_REQUEST.getCode());
}
use of com.linkedin.restli.server.RoutingException in project rest.li by linkedin.
the class RestLiRouter method processResourceTree.
private RoutingResult processResourceTree(final ResourceModel resource, final ServerResourceContext context, final Queue<String> remainingPath) {
ResourceModel currentResource = resource;
// iterate through all path segments, simultaneously descending the resource hierarchy
// and parsing path keys where applicable;
// the goal of this loop is to locate the leaf resource, which will be set in
// currentResource, and to parse the necessary information into the context
ResourceLevel currentLevel = currentResource.getResourceLevel();
while (remainingPath.peek() != null) {
String currentPathSegment = remainingPath.poll();
if (currentLevel.equals(ResourceLevel.ENTITY)) {
currentResource = currentResource.getSubResource(parseSubresourceName(currentPathSegment));
currentLevel = currentResource == null ? ResourceLevel.ANY : currentResource.getResourceLevel();
} else {
ResourceModel currentCollectionResource = currentResource;
if (currentResource.getKeys().isEmpty()) {
throw new RoutingException(String.format("Path key not supported on resource '%s' for URI '%s'", currentResource.getName(), context.getRequestURI()), HttpStatus.S_400_BAD_REQUEST.getCode());
} else if (context.getParameters().containsKey(RestConstants.ALT_KEY_PARAM)) {
parseAlternativeKey(currentResource, context, currentPathSegment);
currentLevel = ResourceLevel.ENTITY;
} else if (currentResource.getKeyClass() == ComplexResourceKey.class) {
parseComplexKey(currentResource, context, currentPathSegment);
currentLevel = ResourceLevel.ENTITY;
} else if (currentResource.getKeyClass() == CompoundKey.class) {
CompoundKey compoundKey;
try {
compoundKey = parseCompoundKey(currentCollectionResource, context, currentPathSegment);
} catch (IllegalArgumentException e) {
throw new RoutingException(String.format("Malformed Compound Key: '%s'", currentPathSegment), HttpStatus.S_400_BAD_REQUEST.getCode(), e);
}
if (compoundKey != null && compoundKey.getPartKeys().containsAll(currentResource.getKeyNames())) {
// full match on key parts means that we are targeting a unique entity
currentLevel = ResourceLevel.ENTITY;
}
} else // Must be a simple key then
{
parseSimpleKey(currentResource, context, currentPathSegment);
currentLevel = ResourceLevel.ENTITY;
}
}
if (currentResource == null) {
throw new RoutingException(HttpStatus.S_404_NOT_FOUND.getCode());
}
}
//now we know the key type, look for batch parameter
parseBatchKeysParameter(currentResource, context);
return findMethodDescriptor(currentResource, currentLevel, context);
}
Aggregations