Search in sources :

Example 36 with RoutingException

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);
}
Also used : RoutingException(com.linkedin.restli.server.RoutingException) TemplateRuntimeException(com.linkedin.data.template.TemplateRuntimeException)

Example 37 with RoutingException

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);
}
Also used : RoutingException(com.linkedin.restli.server.RoutingException) RestLiSyntaxException(com.linkedin.restli.internal.server.util.RestLiSyntaxException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) LinkedList(java.util.LinkedList) ResourceModel(com.linkedin.restli.internal.server.model.ResourceModel)

Example 38 with RoutingException

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());
    }
}
Also used : RoutingException(com.linkedin.restli.server.RoutingException) PathSegmentSyntaxException(com.linkedin.restli.internal.common.PathSegment.PathSegmentSyntaxException) RecordTemplate(com.linkedin.data.template.RecordTemplate)

Example 39 with RoutingException

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());
}
Also used : RoutingException(com.linkedin.restli.server.RoutingException) ResourceMethodDescriptor(com.linkedin.restli.internal.server.model.ResourceMethodDescriptor) ResourceMethod(com.linkedin.restli.common.ResourceMethod)

Example 40 with RoutingException

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);
}
Also used : RoutingException(com.linkedin.restli.server.RoutingException) CompoundKey(com.linkedin.restli.common.CompoundKey) ResourceLevel(com.linkedin.restli.server.ResourceLevel) ResourceModel(com.linkedin.restli.internal.server.model.ResourceModel)

Aggregations

RoutingException (com.linkedin.restli.server.RoutingException)41 RestRequest (com.linkedin.r2.message.rest.RestRequest)15 RoutingResult (com.linkedin.restli.internal.server.RoutingResult)15 ResourceMethodDescriptor (com.linkedin.restli.internal.server.model.ResourceMethodDescriptor)15 Test (org.testng.annotations.Test)15 ResourceModel (com.linkedin.restli.internal.server.model.ResourceModel)12 DataMap (com.linkedin.data.DataMap)7 ServerResourceContext (com.linkedin.restli.internal.server.ServerResourceContext)7 TemplateRuntimeException (com.linkedin.data.template.TemplateRuntimeException)6 ResourceContext (com.linkedin.restli.server.ResourceContext)6 RestLiServiceException (com.linkedin.restli.server.RestLiServiceException)6 RequestContext (com.linkedin.r2.message.RequestContext)5 RestRequestBuilder (com.linkedin.r2.message.rest.RestRequestBuilder)5 CompoundKey (com.linkedin.restli.common.CompoundKey)5 RestLiRequestData (com.linkedin.restli.server.RestLiRequestData)5 ByteString (com.linkedin.data.ByteString)4 ResourceContextImpl (com.linkedin.restli.internal.server.ResourceContextImpl)4 RestLiInternalException (com.linkedin.restli.internal.server.RestLiInternalException)4 CustomString (com.linkedin.restli.server.custom.types.CustomString)4 RestLiTestHelper.buildResourceModel (com.linkedin.restli.server.test.RestLiTestHelper.buildResourceModel)4