Search in sources :

Example 6 with ResourceMethod

use of com.linkedin.restli.common.ResourceMethod in project rest.li by linkedin.

the class TestFilterRequestContextInternalImpl method testFilterRequestContextAdapter.

@Test
@SuppressWarnings("unchecked")
public void testFilterRequestContextAdapter() throws Exception {
    final String resourceName = "resourceName";
    final String resourceNamespace = "resourceNamespace";
    final ResourceMethod methodType = ResourceMethod.GET;
    final DataMap customAnnotations = new DataMap();
    customAnnotations.put("foo", "Bar");
    final ProjectionMode projectionMode = ProjectionMode.AUTOMATIC;
    final MaskTree maskTree = new MaskTree();
    final MaskTree metadataMaskTree = new MaskTree();
    final MaskTree pagingMaskTree = new MaskTree();
    final MutablePathKeys pathKeys = new PathKeysImpl();
    final Map<String, String> requestHeaders = new HashMap<>();
    requestHeaders.put("Key1", "Value1");
    final URI requestUri = new URI("foo.bar.com");
    final ProtocolVersion protoVersion = AllProtocolVersions.BASELINE_PROTOCOL_VERSION;
    final DataMap queryParams = new DataMap();
    queryParams.put("Param1", "Val1");
    final Map<String, Object> localAttrs = new HashMap<>();
    localAttrs.put("Key1", "Val1");
    final RequestContext r2RequestContext = new RequestContext();
    r2RequestContext.putLocalAttr("Key1", "Val1");
    final String finderName = UUID.randomUUID().toString();
    final String batchFinderName = UUID.randomUUID().toString();
    final String actionName = UUID.randomUUID().toString();
    final List<ServiceError> methodServiceErrors = Collections.singletonList(TestServiceError.METHOD_LEVEL_ERROR);
    final List<ServiceError> resourceServiceErrors = Collections.singletonList(TestServiceError.RESOURCE_LEVEL_ERROR);
    final List<Parameter<?>> methodParameters = Collections.singletonList(Mockito.mock(Parameter.class));
    when(resourceModel.getName()).thenReturn(resourceName);
    when(resourceModel.getNamespace()).thenReturn(resourceNamespace);
    when(filterResourceModel.getServiceErrors()).thenReturn(resourceServiceErrors);
    when(resourceMethod.getResourceModel()).thenReturn(resourceModel);
    when(resourceMethod.getMethodType()).thenReturn(methodType);
    when(resourceMethod.getFinderName()).thenReturn(finderName);
    when(resourceMethod.getBatchFinderName()).thenReturn(batchFinderName);
    when(resourceMethod.getActionName()).thenReturn(actionName);
    when(resourceMethod.getCustomAnnotationData()).thenReturn(customAnnotations);
    when(resourceMethod.getMethod()).thenReturn(null);
    when(resourceMethod.getParameters()).thenReturn(methodParameters);
    when(resourceMethod.getServiceErrors()).thenReturn(methodServiceErrors);
    when(context.getProjectionMode()).thenReturn(projectionMode);
    when(context.getProjectionMask()).thenReturn(maskTree);
    when(context.getMetadataProjectionMask()).thenReturn(metadataMaskTree);
    when(context.getPagingProjectionMask()).thenReturn(pagingMaskTree);
    when(context.getPathKeys()).thenReturn(pathKeys);
    when(context.getRequestHeaders()).thenReturn(requestHeaders);
    when(context.getRequestURI()).thenReturn(requestUri);
    when(context.getRestliProtocolVersion()).thenReturn(protoVersion);
    when(context.getParameters()).thenReturn(queryParams);
    when(context.getRawRequestContext()).thenReturn(r2RequestContext);
    FilterRequestContext filterContext = new FilterRequestContextInternalImpl(context, resourceMethod, null);
    filterContext.setProjectionMask(maskTree);
    filterContext.setMetadataProjectionMask(metadataMaskTree);
    filterContext.setPagingProjectionMask(pagingMaskTree);
    assertEquals(filterContext.getFilterResourceModel().getResourceName(), resourceName);
    assertEquals(filterContext.getFilterResourceModel().getResourceNamespace(), resourceNamespace);
    assertEquals(filterContext.getMethodType(), methodType);
    assertEquals(filterContext.getCustomAnnotations(), customAnnotations);
    assertEquals(filterContext.getProjectionMode(), projectionMode);
    assertEquals(filterContext.getProjectionMask(), maskTree);
    assertEquals(filterContext.getMetadataProjectionMask(), metadataMaskTree);
    assertEquals(filterContext.getPagingProjectionMask(), pagingMaskTree);
    assertEquals(filterContext.getPathKeys(), pathKeys);
    assertEquals(filterContext.getRequestHeaders(), requestHeaders);
    assertEquals(filterContext.getRequestURI(), requestUri);
    assertEquals(filterContext.getRestliProtocolVersion(), protoVersion);
    assertEquals(filterContext.getQueryParameters(), queryParams);
    assertEquals(filterContext.getActionName(), actionName);
    assertEquals(filterContext.getFinderName(), finderName);
    assertEquals(filterContext.getBatchFinderName(), batchFinderName);
    assertEquals(filterContext.getRequestContextLocalAttrs(), localAttrs);
    assertNull(filterContext.getMethod());
    assertEquals(filterContext.getMethodParameters(), methodParameters);
    assertNotSame(filterContext.getMethodParameters(), methodParameters);
    assertEquals(filterContext.getMethodServiceErrors(), methodServiceErrors);
    filterContext.getRequestHeaders().put("header2", "value2");
    assertEquals(requestHeaders.get("header2"), "value2");
    verify(resourceModel).getName();
    verify(resourceModel).getNamespace();
    verify(resourceMethod).getMethodType();
    verify(resourceMethod).getResourceModel();
    verify(resourceMethod).getCustomAnnotationData();
    verify(resourceMethod).getFinderName();
    verify(resourceMethod).getBatchFinderName();
    verify(resourceMethod).getActionName();
    verify(resourceMethod).getMethod();
    verify(resourceMethod, times(2)).getParameters();
    verify(resourceMethod).getServiceErrors();
    verify(context).getProjectionMode();
    verify(context).setProjectionMask(maskTree);
    verify(context).getProjectionMask();
    verify(context).setMetadataProjectionMask(metadataMaskTree);
    verify(context).getMetadataProjectionMask();
    verify(context).setPagingProjectionMask(pagingMaskTree);
    verify(context).getPagingProjectionMask();
    verify(context).getPathKeys();
    verify(context, times(2)).getRequestHeaders();
    verify(context).getRequestURI();
    verify(context).getRestliProtocolVersion();
    verify(context).getParameters();
    verify(context).getRawRequestContext();
    verify(resourceMethod).getCollectionCustomMetadataType();
    verifyNoMoreInteractions(context, resourceMethod, resourceModel);
}
Also used : TestServiceError(com.linkedin.restli.server.TestServiceError) ServiceError(com.linkedin.restli.server.errors.ServiceError) MutablePathKeys(com.linkedin.restli.internal.server.MutablePathKeys) HashMap(java.util.HashMap) PathKeysImpl(com.linkedin.restli.internal.server.PathKeysImpl) ProtocolVersion(com.linkedin.restli.common.ProtocolVersion) URI(java.net.URI) DataMap(com.linkedin.data.DataMap) MaskTree(com.linkedin.data.transform.filter.request.MaskTree) ProjectionMode(com.linkedin.restli.server.ProjectionMode) Parameter(com.linkedin.restli.internal.server.model.Parameter) FilterRequestContext(com.linkedin.restli.server.filter.FilterRequestContext) RequestContext(com.linkedin.r2.message.RequestContext) FilterRequestContext(com.linkedin.restli.server.filter.FilterRequestContext) ResourceMethod(com.linkedin.restli.common.ResourceMethod) Test(org.testng.annotations.Test) BeforeTest(org.testng.annotations.BeforeTest)

Example 7 with ResourceMethod

use of com.linkedin.restli.common.ResourceMethod in project rest.li by linkedin.

the class RestLiValidationFilter method onResponse.

@SuppressWarnings("unchecked")
public CompletableFuture<Void> onResponse(final FilterRequestContext requestContext, final FilterResponseContext responseContext) {
    RestLiResponseData<?> responseData = responseContext.getResponseData();
    if (responseData.getResponseEnvelope().isErrorResponse()) {
        return CompletableFuture.completedFuture(null);
    }
    if (shouldValidateOnResponse(requestContext)) {
        ResourceMethod method = requestContext.getMethodType();
        RestLiDataValidator validator = createResponseRestLiDataValidator(requestContext);
        switch(method) {
            case GET:
                validateSingleResponse(validator, ((GetResponseEnvelope) responseData.getResponseEnvelope()).getRecord());
                break;
            case CREATE:
                if (requestContext.isReturnEntityMethod() && requestContext.isReturnEntityRequested()) {
                    validateSingleResponse(validator, ((CreateResponseEnvelope) responseData.getResponseEnvelope()).getRecord());
                }
                break;
            case PARTIAL_UPDATE:
                if (requestContext.isReturnEntityMethod() && requestContext.isReturnEntityRequested()) {
                    validateSingleResponse(validator, ((PartialUpdateResponseEnvelope) responseData.getResponseEnvelope()).getRecord());
                }
                break;
            case GET_ALL:
                validateCollectionResponse(validator, ((GetAllResponseEnvelope) responseData.getResponseEnvelope()).getCollectionResponse());
                break;
            case FINDER:
                validateCollectionResponse(validator, ((FinderResponseEnvelope) responseData.getResponseEnvelope()).getCollectionResponse());
                break;
            case BATCH_FINDER:
                validateBatchCollectionResponse(validator, ((BatchFinderResponseEnvelope) responseData.getResponseEnvelope()).getItems());
                break;
            case BATCH_GET:
                validateBatchResponse(validator, ((BatchGetResponseEnvelope) responseData.getResponseEnvelope()).getBatchResponseMap());
                break;
            case BATCH_CREATE:
                if (requestContext.isReturnEntityMethod() && requestContext.isReturnEntityRequested()) {
                    validateCreateCollectionResponse(validator, ((BatchCreateResponseEnvelope) responseData.getResponseEnvelope()).getCreateResponses());
                }
                break;
            case BATCH_PARTIAL_UPDATE:
                if (requestContext.isReturnEntityMethod() && requestContext.isReturnEntityRequested()) {
                    validateBatchResponse(validator, ((BatchPartialUpdateResponseEnvelope) responseData.getResponseEnvelope()).getBatchResponseMap());
                }
                break;
        }
    }
    return CompletableFuture.completedFuture(null);
}
Also used : RestLiDataValidator(com.linkedin.restli.common.validation.RestLiDataValidator) ResourceMethod(com.linkedin.restli.common.ResourceMethod)

Example 8 with ResourceMethod

use of com.linkedin.restli.common.ResourceMethod in project rest.li by linkedin.

the class RestLiValidationFilter method onRequest.

@Override
public CompletableFuture<Void> onRequest(final FilterRequestContext requestContext) {
    // are spotted early
    if (shouldValidateOnResponse(requestContext)) {
        MaskTree projectionMask = requestContext.getProjectionMask();
        if (projectionMask != null) {
            try {
                // Value class from resource model is the only source of truth for record schema.
                // Schema from the record template itself should not be used.
                DataSchema originalSchema = DataTemplateUtil.getSchema(requestContext.getFilterResourceModel().getValueClass());
                DataSchema validatingSchema = constructValidatingSchema(requestContext, originalSchema, projectionMask.getDataMap(), _nonSchemaFieldsToAllowInProjectionMask);
                // Put validating schema in scratchpad for use in onResponse
                requestContext.getFilterScratchpad().put(VALIDATING_SCHEMA_KEY, validatingSchema);
            } catch (InvalidProjectionException e) {
                throw new RestLiServiceException(HttpStatus.S_400_BAD_REQUEST, e.getMessage());
            } catch (TemplateRuntimeException e) {
                throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, TEMPLATE_RUNTIME_EXCEPTION_MESSAGE);
            }
        }
    }
    if (!shouldValidateOnRequest(requestContext)) {
        return CompletableFuture.completedFuture(null);
    }
    Class<?> resourceClass = requestContext.getFilterResourceModel().getResourceClass();
    if (UnstructuredDataUtil.isUnstructuredDataClass(resourceClass)) {
        return CompletableFuture.completedFuture(null);
    }
    ResourceMethod method = requestContext.getMethodType();
    RestLiDataValidator validator = createRequestRestLiDataValidator(requestContext);
    RestLiRequestData requestData = requestContext.getRequestData();
    ValidationResult result;
    switch(method) {
        case CREATE:
        case UPDATE:
            result = validator.validateInput(requestData.getEntity());
            if (!result.isValid()) {
                throw constructRestLiServiceException(result.getMessages(), result.getMessages().toString());
            }
            break;
        case PARTIAL_UPDATE:
            result = validator.validateInput((PatchRequest<?>) requestData.getEntity());
            if (!result.isValid()) {
                throw constructRestLiServiceException(result.getMessages(), result.getMessages().toString());
            }
            break;
        case BATCH_CREATE:
            StringBuilder errorMessage = new StringBuilder();
            Map<String, Collection<Message>> messages = new HashMap<>();
            int index = 0;
            for (RecordTemplate entity : requestData.getBatchEntities()) {
                result = validator.validateInput(entity);
                if (!result.isValid()) {
                    errorMessage.append("Index: ").append(index).append(", ").append(result.getMessages().toString());
                    messages.put(String.valueOf(index), result.getMessages());
                }
                ++index;
            }
            if (errorMessage.length() > 0) {
                throw constructRestLiServiceException(messages, errorMessage.toString());
            }
            break;
        case BATCH_UPDATE:
        case BATCH_PARTIAL_UPDATE:
            ProtocolVersion protocolVersion = requestContext.getRestliProtocolVersion();
            StringBuilder stringBuilder = new StringBuilder();
            Map<String, Collection<Message>> errorMessages = new HashMap<>();
            for (Map.Entry<?, ? extends RecordTemplate> entry : requestData.getBatchKeyEntityMap().entrySet()) {
                if (method == ResourceMethod.BATCH_UPDATE) {
                    result = validator.validateInput(entry.getValue());
                } else {
                    result = validator.validateInput((PatchRequest<?>) entry.getValue());
                }
                if (!result.isValid()) {
                    stringBuilder.append("Key: ").append(entry.getKey()).append(", ").append(result.getMessages().toString());
                    errorMessages.put(URIParamUtils.encodeKeyForBody(entry.getKey(), false, protocolVersion), result.getMessages());
                }
            }
            if (stringBuilder.length() > 0) {
                throw constructRestLiServiceException(errorMessages, stringBuilder.toString());
            }
            break;
        default:
            break;
    }
    return CompletableFuture.completedFuture(null);
}
Also used : InvalidProjectionException(com.linkedin.restli.common.util.ProjectionMaskApplier.InvalidProjectionException) HashMap(java.util.HashMap) ValidationResult(com.linkedin.data.schema.validation.ValidationResult) PatchRequest(com.linkedin.restli.common.PatchRequest) ProtocolVersion(com.linkedin.restli.common.ProtocolVersion) DataSchema(com.linkedin.data.schema.DataSchema) RestLiServiceException(com.linkedin.restli.server.RestLiServiceException) MaskTree(com.linkedin.data.transform.filter.request.MaskTree) RestLiDataValidator(com.linkedin.restli.common.validation.RestLiDataValidator) RecordTemplate(com.linkedin.data.template.RecordTemplate) TemplateRuntimeException(com.linkedin.data.template.TemplateRuntimeException) Collection(java.util.Collection) HashMap(java.util.HashMap) DataMap(com.linkedin.data.DataMap) Map(java.util.Map) ResourceMethod(com.linkedin.restli.common.ResourceMethod) RestLiRequestData(com.linkedin.restli.server.RestLiRequestData)

Example 9 with ResourceMethod

use of com.linkedin.restli.common.ResourceMethod in project rest.li by linkedin.

the class ResourceMethodConfigElement method parse.

static ResourceMethodConfigElement parse(RestLiMethodConfig.ConfigType configType, String key, Object value) throws ResourceMethodConfigParsingException {
    ParsingErrorListener errorListener = new ParsingErrorListener();
    ANTLRInputStream input = new ANTLRInputStream(key);
    ResourceMethodKeyLexer lexer = new ResourceMethodKeyLexer(input);
    lexer.removeErrorListeners();
    lexer.addErrorListener(errorListener);
    CommonTokenStream tokens = new CommonTokenStream(lexer);
    ResourceMethodKeyParser parser = new ResourceMethodKeyParser(tokens);
    parser.removeErrorListeners();
    parser.addErrorListener(errorListener);
    ResourceMethodKeyParser.KeyContext keyTree = parser.key();
    if (!errorListener.hasErrors()) {
        Optional<String> resourceName = handlingWildcard(keyTree.restResource());
        Optional<ResourceMethod> opType = getOpType(keyTree.operation());
        Optional<String> opName = opType.flatMap(method -> getOpName(method, keyTree.operation()));
        return new ResourceMethodConfigElement(key, coerceValue(configType, value), configType, resourceName, opType, opName);
    } else {
        throw new ResourceMethodConfigParsingException("Error" + ((errorListener.errorsSize() > 1) ? "s" : "") + " parsing key: " + key + "\n" + errorListener);
    }
}
Also used : CommonTokenStream(org.antlr.v4.runtime.CommonTokenStream) ANTLRInputStream(org.antlr.v4.runtime.ANTLRInputStream) ResourceMethod(com.linkedin.restli.common.ResourceMethod)

Example 10 with ResourceMethod

use of com.linkedin.restli.common.ResourceMethod in project rest.li by linkedin.

the class TestBatchUpdateResponseBuilder method dataProvider.

@DataProvider(name = "testData")
public Object[][] dataProvider() {
    CompoundKey c1 = new CompoundKey().append("a", "a1").append("b", 1);
    CompoundKey c2 = new CompoundKey().append("a", "a2").append("b", 2);
    CompoundKey c3 = new CompoundKey().append("a", "a3").append("b", 3);
    Map<CompoundKey, UpdateResponse> results = new HashMap<>();
    results.put(c1, new UpdateResponse(HttpStatus.S_202_ACCEPTED));
    results.put(c2, new UpdateResponse(HttpStatus.S_202_ACCEPTED));
    RestLiServiceException restLiServiceException = new RestLiServiceException(HttpStatus.S_404_NOT_FOUND);
    Map<CompoundKey, RestLiServiceException> errors = Collections.singletonMap(c3, restLiServiceException);
    BatchUpdateResult<CompoundKey, Foo> batchUpdateResult = new BatchUpdateResult<>(results, errors);
    Map<CompoundKey, UpdateResponse> keyOverlapResults = new HashMap<>();
    keyOverlapResults.put(c1, new UpdateResponse(HttpStatus.S_202_ACCEPTED));
    keyOverlapResults.put(c2, new UpdateResponse(HttpStatus.S_202_ACCEPTED));
    keyOverlapResults.put(c3, new UpdateResponse(HttpStatus.S_404_NOT_FOUND));
    BatchUpdateResult<CompoundKey, Foo> keyOverlapBatchUpdateResult = new BatchUpdateResult<>(keyOverlapResults, errors);
    UpdateStatus updateStatus = new UpdateStatus().setStatus(202);
    ErrorResponse errorResponse = new ErrorResponse().setStatus(404);
    Map<String, UpdateStatus> expectedProtocol1Results = new HashMap<>();
    expectedProtocol1Results.put("a=a1&b=1", updateStatus);
    expectedProtocol1Results.put("a=a2&b=2", updateStatus);
    Map<String, ErrorResponse> expectedProtocol1Errors = new HashMap<>();
    expectedProtocol1Errors.put("a=a3&b=3", errorResponse);
    Map<String, UpdateStatus> expectedProtocol2Results = new HashMap<>();
    expectedProtocol2Results.put("(a:a1,b:1)", updateStatus);
    expectedProtocol2Results.put("(a:a2,b:2)", updateStatus);
    Map<String, ErrorResponse> expectedProtocol2Errors = new HashMap<>();
    expectedProtocol2Errors.put("(a:a3,b:3)", errorResponse);
    Map<String, UpdateStatus> expectedAltKeyResults = new HashMap<>();
    expectedAltKeyResults.put("aa1xb1", updateStatus);
    expectedAltKeyResults.put("aa2xb2", updateStatus);
    Map<String, ErrorResponse> expectedAltKeyErrors = new HashMap<>();
    expectedAltKeyErrors.put("aa3xb3", errorResponse);
    Map<String, AlternativeKey<?, ?>> alternativeKeyMap = new HashMap<>();
    alternativeKeyMap.put("alt", new AlternativeKey<>(new TestKeyCoercer(), String.class, new StringDataSchema()));
    List<Object[]> data = new ArrayList<>();
    for (ResourceMethod resourceMethod : BUILDERS.keySet()) {
        data.add(new Object[] { batchUpdateResult, null, null, expectedProtocol1Results, expectedProtocol1Errors, AllProtocolVersions.RESTLI_PROTOCOL_1_0_0.getProtocolVersion(), resourceMethod });
        data.add(new Object[] { batchUpdateResult, null, null, expectedProtocol2Results, expectedProtocol2Errors, AllProtocolVersions.RESTLI_PROTOCOL_2_0_0.getProtocolVersion(), resourceMethod });
        data.add(new Object[] { batchUpdateResult, "alt", alternativeKeyMap, expectedAltKeyResults, expectedAltKeyErrors, AllProtocolVersions.RESTLI_PROTOCOL_1_0_0.getProtocolVersion(), resourceMethod });
        data.add(new Object[] { batchUpdateResult, "alt", alternativeKeyMap, expectedAltKeyResults, expectedAltKeyErrors, AllProtocolVersions.RESTLI_PROTOCOL_2_0_0.getProtocolVersion(), resourceMethod });
        data.add(new Object[] { keyOverlapBatchUpdateResult, null, null, expectedProtocol2Results, expectedProtocol2Errors, AllProtocolVersions.RESTLI_PROTOCOL_2_0_0.getProtocolVersion(), resourceMethod });
    }
    return data.toArray(new Object[data.size()][]);
}
Also used : UpdateStatus(com.linkedin.restli.common.UpdateStatus) CompoundKey(com.linkedin.restli.common.CompoundKey) HashMap(java.util.HashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Foo(com.linkedin.pegasus.generator.examples.Foo) ArrayList(java.util.ArrayList) ErrorResponse(com.linkedin.restli.common.ErrorResponse) StringDataSchema(com.linkedin.data.schema.StringDataSchema) UpdateResponse(com.linkedin.restli.server.UpdateResponse) RestLiServiceException(com.linkedin.restli.server.RestLiServiceException) BatchUpdateResult(com.linkedin.restli.server.BatchUpdateResult) AlternativeKey(com.linkedin.restli.server.AlternativeKey) ResourceMethod(com.linkedin.restli.common.ResourceMethod) DataProvider(org.testng.annotations.DataProvider)

Aggregations

ResourceMethod (com.linkedin.restli.common.ResourceMethod)54 Test (org.testng.annotations.Test)19 HashMap (java.util.HashMap)18 ResourceSpecImpl (com.linkedin.restli.common.ResourceSpecImpl)13 DataMap (com.linkedin.data.DataMap)12 TestRecord (com.linkedin.restli.client.test.TestRecord)12 DynamicRecordMetadata (com.linkedin.data.template.DynamicRecordMetadata)10 ArrayList (java.util.ArrayList)8 Map (java.util.Map)8 ProtocolVersion (com.linkedin.restli.common.ProtocolVersion)6 RestLiServiceException (com.linkedin.restli.server.RestLiServiceException)6 ResourceMethodDescriptor (com.linkedin.restli.internal.server.model.ResourceMethodDescriptor)5 ValidationResult (com.linkedin.data.schema.validation.ValidationResult)4 RecordTemplate (com.linkedin.data.template.RecordTemplate)4 Foo (com.linkedin.pegasus.generator.examples.Foo)4 RoutingResult (com.linkedin.restli.internal.server.RoutingResult)4 ResourceSchemaArray (com.linkedin.restli.restspec.ResourceSchemaArray)4 JClass (com.sun.codemodel.JClass)4 JDefinedClass (com.sun.codemodel.JDefinedClass)4 ByteString (com.linkedin.data.ByteString)3