Search in sources :

Example 31 with ServerResourceContext

use of com.linkedin.restli.internal.server.ServerResourceContext in project rest.li by linkedin.

the class TestRestLiResponseHandler method buildRoutingResult.

private final RoutingResult buildRoutingResult(ResourceMethod resourceMethod, RestRequest request, Map<String, String> acceptHeaders) throws SecurityException, NoSuchMethodException, RestLiSyntaxException {
    Method method = ProjectionTestFixture.class.getMethod("batchGet", Set.class);
    ResourceModel model = RestLiTestHelper.buildResourceModel(StatusCollectionResource.class);
    ResourceMethodDescriptor methodDescriptor = ResourceMethodDescriptor.createForRestful(resourceMethod, method, InterfaceType.SYNC);
    model.addResourceMethodDescriptor(methodDescriptor);
    ServerResourceContext context = new ResourceContextImpl(new PathKeysImpl(), request, new RequestContext());
    RestUtils.validateRequestHeadersAndUpdateResourceContext(acceptHeaders, context);
    return new RoutingResult(context, methodDescriptor);
}
Also used : RoutingResult(com.linkedin.restli.internal.server.RoutingResult) ServerResourceContext(com.linkedin.restli.internal.server.ServerResourceContext) PathKeysImpl(com.linkedin.restli.internal.server.PathKeysImpl) ResourceMethodDescriptor(com.linkedin.restli.internal.server.model.ResourceMethodDescriptor) ResourceModel(com.linkedin.restli.internal.server.model.ResourceModel) RestLiTestHelper.buildResourceModel(com.linkedin.restli.server.test.RestLiTestHelper.buildResourceModel) ResourceMethod(com.linkedin.restli.common.ResourceMethod) Method(java.lang.reflect.Method) RequestContext(com.linkedin.r2.message.RequestContext) ResourceContextImpl(com.linkedin.restli.internal.server.ResourceContextImpl)

Example 32 with ServerResourceContext

use of com.linkedin.restli.internal.server.ServerResourceContext in project rest.li by linkedin.

the class TestRestLiResponseHandler method invokeResponseHandler.

private RestResponse invokeResponseHandler(String uri, ResourceMethodDescriptor methodDescriptor, Object result, Map<String, String> headers, ProtocolVersion protocolVersion) throws IOException, URISyntaxException, RestLiSyntaxException {
    RestRequest request = buildRequest(uri, headers, protocolVersion);
    ServerResourceContext context = new ResourceContextImpl(new PathKeysImpl(), request, new RequestContext());
    RestUtils.validateRequestHeadersAndUpdateResourceContext(headers, context);
    RoutingResult routingResult = new RoutingResult(context, methodDescriptor);
    RestResponse response;
    response = _responseHandler.buildResponse(request, routingResult, result);
    return response;
}
Also used : RoutingResult(com.linkedin.restli.internal.server.RoutingResult) RestRequest(com.linkedin.r2.message.rest.RestRequest) ServerResourceContext(com.linkedin.restli.internal.server.ServerResourceContext) PathKeysImpl(com.linkedin.restli.internal.server.PathKeysImpl) RestResponse(com.linkedin.r2.message.rest.RestResponse) PartialRestResponse(com.linkedin.restli.internal.server.response.PartialRestResponse) RequestContext(com.linkedin.r2.message.RequestContext) ResourceContextImpl(com.linkedin.restli.internal.server.ResourceContextImpl)

Example 33 with ServerResourceContext

use of com.linkedin.restli.internal.server.ServerResourceContext in project rest.li by linkedin.

the class RestLiServer method handleResourceRequest.

private void handleResourceRequest(final RestRequest request, final RequestContext requestContext, final RequestExecutionCallback<RestResponse> callback, final RestLiAttachmentReader attachmentReader, final boolean isDebugMode) {
    try {
        ensureRequestUsesValidRestliProtocol(request);
    } catch (RestLiServiceException e) {
        respondWithPreRoutingError(e, request, attachmentReader, callback);
        return;
    }
    final RoutingResult method;
    try {
        method = _router.process(request, requestContext, attachmentReader);
    } catch (Exception e) {
        respondWithPreRoutingError(e, request, attachmentReader, callback);
        return;
    }
    final RequestExecutionCallback<RestResponse> wrappedCallback = notifyInvokeAwares(method, callback);
    RequestExecutionReportBuilder requestExecutionReportBuilder = null;
    if (isDebugMode) {
        requestExecutionReportBuilder = new RequestExecutionReportBuilder();
    }
    final FilterRequestContextInternal filterContext = new FilterRequestContextInternalImpl((ServerResourceContext) method.getContext(), method.getResourceMethod());
    RestLiArgumentBuilder adapter;
    try {
        RestUtils.validateRequestHeadersAndUpdateResourceContext(request.getHeaders(), (ServerResourceContext) method.getContext());
        adapter = buildRestLiArgumentBuilder(method, _errorResponseBuilder);
        filterContext.setRequestData(adapter.extractRequestData(method, request));
    } catch (Exception e) {
        // would not trigger response filters because request filters haven't run yet
        wrappedCallback.onError(e, requestExecutionReportBuilder == null ? null : requestExecutionReportBuilder.build(), ((ServerResourceContext) method.getContext()).getRequestAttachmentReader(), null);
        return;
    }
    RestLiFilterResponseContextFactory<Object> filterResponseContextFactory = new RestLiFilterResponseContextFactory<Object>(request, method, _responseHandler);
    FilterChainCallback filterChainCallback = new FilterChainCallbackImpl(method, _methodInvoker, adapter, requestExecutionReportBuilder, attachmentReader, _responseHandler, wrappedCallback);
    RestLiFilterChain filterChain = new RestLiFilterChain(_filters, filterChainCallback);
    filterChain.onRequest(filterContext, filterResponseContextFactory);
}
Also used : FilterRequestContextInternalImpl(com.linkedin.restli.internal.server.filter.FilterRequestContextInternalImpl) RestResponse(com.linkedin.r2.message.rest.RestResponse) RestLiArgumentBuilder(com.linkedin.restli.internal.server.methods.arguments.RestLiArgumentBuilder) MultiPartIllegalFormatException(com.linkedin.multipart.exceptions.MultiPartIllegalFormatException) ParseException(javax.mail.internet.ParseException) RestException(com.linkedin.r2.message.rest.RestException) RestLiAttachmentReaderException(com.linkedin.restli.common.attachments.RestLiAttachmentReaderException) RestLiFilterChain(com.linkedin.restli.internal.server.filter.RestLiFilterChain) RoutingResult(com.linkedin.restli.internal.server.RoutingResult) FilterChainCallback(com.linkedin.restli.internal.server.filter.FilterChainCallback) RestLiFilterResponseContextFactory(com.linkedin.restli.internal.server.filter.RestLiFilterResponseContextFactory) FilterRequestContextInternal(com.linkedin.restli.internal.server.filter.FilterRequestContextInternal) ServerResourceContext(com.linkedin.restli.internal.server.ServerResourceContext) FilterChainCallbackImpl(com.linkedin.restli.internal.server.filter.FilterChainCallbackImpl)

Example 34 with ServerResourceContext

use of com.linkedin.restli.internal.server.ServerResourceContext in project rest.li by linkedin.

the class BatchGetResponseBuilder method buildRestLiResponseData.

@Override
public RestLiResponseData buildRestLiResponseData(RestRequest request, RoutingResult routingResult, Object result, Map<String, String> headers, List<HttpCookie> cookies) {
    @SuppressWarnings({ "unchecked" }) final Map<Object, RecordTemplate> /** constrained by signature of {@link com.linkedin.restli.server.resources.CollectionResource#batchGet(java.util.Set)} */
    entities = (Map<Object, RecordTemplate>) result;
    Map<Object, HttpStatus> statuses = Collections.emptyMap();
    Map<Object, RestLiServiceException> serviceErrors = Collections.emptyMap();
    if (result instanceof BatchResult) {
        @SuppressWarnings({ "unchecked" }) final BatchResult<Object, RecordTemplate> /** constrained by signature of {@link com.linkedin.restli.server.resources.CollectionResource#batchGet(java.util.Set)} */
        batchResult = (BatchResult<Object, RecordTemplate>) result;
        statuses = batchResult.getStatuses();
        serviceErrors = batchResult.getErrors();
    }
    try {
        if (statuses.containsKey(null)) {
            throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Unexpected null encountered. Null key inside of a Map returned by the resource method: " + routingResult.getResourceMethod());
        }
    } catch (NullPointerException e) {
    // Some map implementations will throw an NPE if they do not support null keys.
    // In this case it is OK to swallow this exception and proceed.
    }
    Map<Object, BatchResponseEntry> batchResult = new HashMap<Object, BatchResponseEntry>(entities.size() + serviceErrors.size());
    for (Map.Entry<Object, RecordTemplate> entity : entities.entrySet()) {
        if (entity.getKey() == null) {
            throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Unexpected null encountered. Null key inside of a Map returned by the resource method: " + routingResult.getResourceMethod());
        }
        Object finalKey = ResponseUtils.translateCanonicalKeyToAlternativeKeyIfNeeded(entity.getKey(), routingResult);
        final DataMap projectedData = RestUtils.projectFields(entity.getValue().data(), routingResult.getContext().getProjectionMode(), routingResult.getContext().getProjectionMask());
        AnyRecord anyRecord = new AnyRecord(projectedData);
        batchResult.put(finalKey, new BatchResponseEntry(statuses.get(entity.getKey()), anyRecord));
    }
    for (Map.Entry<Object, RestLiServiceException> entity : serviceErrors.entrySet()) {
        if (entity.getKey() == null || entity.getValue() == null) {
            throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Unexpected null encountered. Null key inside of a Map returned by the resource method: " + routingResult.getResourceMethod());
        }
        Object finalKey = ResponseUtils.translateCanonicalKeyToAlternativeKeyIfNeeded(entity.getKey(), routingResult);
        batchResult.put(finalKey, new BatchResponseEntry(statuses.get(entity.getKey()), entity.getValue()));
    }
    final Map<Object, RestLiServiceException> contextErrors = ((ServerResourceContext) routingResult.getContext()).getBatchKeyErrors();
    for (Map.Entry<Object, RestLiServiceException> entry : contextErrors.entrySet()) {
        Object finalKey = ResponseUtils.translateCanonicalKeyToAlternativeKeyIfNeeded(entry.getKey(), routingResult);
        batchResult.put(finalKey, new BatchResponseEntry(statuses.get(entry.getKey()), entry.getValue()));
    }
    RestLiResponseDataImpl responseData = new RestLiResponseDataImpl(HttpStatus.S_200_OK, headers, cookies);
    responseData.setResponseEnvelope(new BatchGetResponseEnvelope(batchResult, responseData));
    return responseData;
}
Also used : AnyRecord(com.linkedin.restli.internal.server.methods.AnyRecord) HttpStatus(com.linkedin.restli.common.HttpStatus) HashMap(java.util.HashMap) BatchResult(com.linkedin.restli.server.BatchResult) DataMap(com.linkedin.data.DataMap) BatchResponseEntry(com.linkedin.restli.internal.server.response.BatchResponseEnvelope.BatchResponseEntry) RestLiServiceException(com.linkedin.restli.server.RestLiServiceException) ServerResourceContext(com.linkedin.restli.internal.server.ServerResourceContext) RecordTemplate(com.linkedin.data.template.RecordTemplate) HashMap(java.util.HashMap) DataMap(com.linkedin.data.DataMap) Map(java.util.Map)

Example 35 with ServerResourceContext

use of com.linkedin.restli.internal.server.ServerResourceContext in project rest.li by linkedin.

the class ArgumentBuilder method buildArgs.

/**
   * Build arguments for resource method invocation. Combines various types of arguments
   * into a single array.
   *
   * @param positionalArguments pass-through arguments coming from
   *          {@link RestLiArgumentBuilder}
   * @param resourceMethod the resource method
   * @param context {@link ResourceContext}
   * @param template {@link DynamicRecordTemplate}
   * @return array of method argument for method invocation.
   */
@SuppressWarnings("deprecation")
public static Object[] buildArgs(final Object[] positionalArguments, final ResourceMethodDescriptor resourceMethod, final ResourceContext context, final DynamicRecordTemplate template) {
    List<Parameter<?>> parameters = resourceMethod.getParameters();
    Object[] arguments = Arrays.copyOf(positionalArguments, parameters.size());
    fixUpComplexKeySingletonArraysInArguments(arguments);
    boolean attachmentsDesired = false;
    for (int i = positionalArguments.length; i < parameters.size(); ++i) {
        Parameter<?> param = parameters.get(i);
        try {
            if (param.getParamType() == Parameter.ParamType.KEY || param.getParamType() == Parameter.ParamType.ASSOC_KEY_PARAM) {
                Object value = context.getPathKeys().get(param.getName());
                if (value != null) {
                    arguments[i] = value;
                    continue;
                }
            } else if (param.getParamType() == Parameter.ParamType.CALLBACK) {
                continue;
            } else if (param.getParamType() == Parameter.ParamType.PARSEQ_CONTEXT_PARAM || param.getParamType() == Parameter.ParamType.PARSEQ_CONTEXT) {
                // don't know what to fill in yet
                continue;
            } else if (param.getParamType() == Parameter.ParamType.HEADER) {
                HeaderParam headerParam = param.getAnnotations().get(HeaderParam.class);
                String value = context.getRequestHeaders().get(headerParam.value());
                arguments[i] = value;
                continue;
            } else //we must evaluate based on the param type (annotation used)
            if (param.getParamType() == Parameter.ParamType.PROJECTION || param.getParamType() == Parameter.ParamType.PROJECTION_PARAM) {
                arguments[i] = context.getProjectionMask();
                continue;
            } else if (param.getParamType() == Parameter.ParamType.METADATA_PROJECTION_PARAM) {
                arguments[i] = context.getMetadataProjectionMask();
                continue;
            } else if (param.getParamType() == Parameter.ParamType.PAGING_PROJECTION_PARAM) {
                arguments[i] = context.getPagingProjectionMask();
                continue;
            } else if (param.getParamType() == Parameter.ParamType.CONTEXT || param.getParamType() == Parameter.ParamType.PAGING_CONTEXT_PARAM) {
                PagingContext ctx = RestUtils.getPagingContext(context, (PagingContext) param.getDefaultValue());
                arguments[i] = ctx;
                continue;
            } else if (param.getParamType() == Parameter.ParamType.PATH_KEYS || param.getParamType() == Parameter.ParamType.PATH_KEYS_PARAM) {
                arguments[i] = context.getPathKeys();
                continue;
            } else if (param.getParamType() == Parameter.ParamType.PATH_KEY_PARAM) {
                Object value = context.getPathKeys().get(param.getName());
                if (value != null) {
                    arguments[i] = value;
                    continue;
                }
            } else if (param.getParamType() == Parameter.ParamType.RESOURCE_CONTEXT || param.getParamType() == Parameter.ParamType.RESOURCE_CONTEXT_PARAM) {
                arguments[i] = context;
                continue;
            } else if (param.getParamType() == Parameter.ParamType.VALIDATOR_PARAM) {
                RestLiDataValidator validator = new RestLiDataValidator(resourceMethod.getResourceModel().getResourceClass().getAnnotations(), resourceMethod.getResourceModel().getValueClass(), resourceMethod.getMethodType());
                arguments[i] = validator;
                continue;
            } else if (param.getParamType() == Parameter.ParamType.RESTLI_ATTACHMENTS_PARAM) {
                arguments[i] = ((ServerResourceContext) context).getRequestAttachmentReader();
                attachmentsDesired = true;
                continue;
            } else if (param.getParamType() == Parameter.ParamType.POST) {
                // handle action parameters
                if (template != null) {
                    DataMap data = template.data();
                    if (data.containsKey(param.getName())) {
                        arguments[i] = template.getValue(param);
                        continue;
                    }
                }
            } else if (param.getParamType() == Parameter.ParamType.QUERY) {
                Object value;
                if (DataTemplate.class.isAssignableFrom(param.getType())) {
                    value = buildDataTemplateArgument(context, param);
                } else {
                    value = buildRegularArgument(context, param);
                }
                if (value != null) {
                    arguments[i] = value;
                    continue;
                }
            } else if (param.getParamType() == Parameter.ParamType.BATCH || param.getParamType() == Parameter.ParamType.RESOURCE_KEY) {
                // should not come to this routine since it should be handled by passing in positionalArguments
                throw new RoutingException("Parameter '" + param.getName() + "' should be passed in as a positional argument", HttpStatus.S_400_BAD_REQUEST.getCode());
            } else {
                // unknown param type
                throw new RoutingException("Parameter '" + param.getName() + "' has an unknown parameter type '" + param.getParamType().name() + "'", HttpStatus.S_400_BAD_REQUEST.getCode());
            }
        } catch (TemplateRuntimeException e) {
            throw new RoutingException("Parameter '" + param.getName() + "' is invalid", HttpStatus.S_400_BAD_REQUEST.getCode());
        }
        try {
            // check if it is optional parameter
            if (param.isOptional() && param.hasDefaultValue()) {
                arguments[i] = param.getDefaultValue();
            } else if (param.isOptional() && !param.getType().isPrimitive()) {
                // optional primitive parameter must have default value or provided
                arguments[i] = null;
            } else {
                throw new RoutingException("Parameter '" + param.getName() + "' is required", HttpStatus.S_400_BAD_REQUEST.getCode());
            }
        } catch (ResourceConfigException e) {
            // Parameter default value format exception should result in server error code 500.
            throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Parameter '" + param.getName() + "' default value is invalid", e);
        }
    }
    //that were not needed is safe, but not for request attachments.
    if (!attachmentsDesired && ((ServerResourceContext) context).getRequestAttachmentReader() != null) {
        throw new RestLiServiceException(HttpStatus.S_400_BAD_REQUEST, "Resource method endpoint invoked does not accept any request attachments.");
    }
    return arguments;
}
Also used : RoutingException(com.linkedin.restli.server.RoutingException) HeaderParam(com.linkedin.restli.server.annotations.HeaderParam) DataMap(com.linkedin.data.DataMap) QueryParamsDataMap(com.linkedin.restli.internal.common.QueryParamsDataMap) RestLiServiceException(com.linkedin.restli.server.RestLiServiceException) RestLiDataValidator(com.linkedin.restli.common.validation.RestLiDataValidator) ServerResourceContext(com.linkedin.restli.internal.server.ServerResourceContext) PagingContext(com.linkedin.restli.server.PagingContext) TemplateRuntimeException(com.linkedin.data.template.TemplateRuntimeException) Parameter(com.linkedin.restli.internal.server.model.Parameter) ResourceConfigException(com.linkedin.restli.server.ResourceConfigException)

Aggregations

ServerResourceContext (com.linkedin.restli.internal.server.ServerResourceContext)55 Test (org.testng.annotations.Test)28 RoutingResult (com.linkedin.restli.internal.server.RoutingResult)18 Parameter (com.linkedin.restli.internal.server.model.Parameter)15 ResourceContextImpl (com.linkedin.restli.internal.server.ResourceContextImpl)14 DataMap (com.linkedin.data.DataMap)13 RestLiServiceException (com.linkedin.restli.server.RestLiServiceException)12 HashMap (java.util.HashMap)11 RequestContext (com.linkedin.r2.message.RequestContext)10 PathKeysImpl (com.linkedin.restli.internal.server.PathKeysImpl)10 ResourceMethodDescriptor (com.linkedin.restli.internal.server.model.ResourceMethodDescriptor)9 RestRequest (com.linkedin.r2.message.rest.RestRequest)8 RestLiAttachmentReader (com.linkedin.restli.common.attachments.RestLiAttachmentReader)7 URI (java.net.URI)7 ByteString (com.linkedin.data.ByteString)6 RestRequestBuilder (com.linkedin.r2.message.rest.RestRequestBuilder)6 RestResponse (com.linkedin.r2.message.rest.RestResponse)6 RoutingException (com.linkedin.restli.server.RoutingException)6 MaskTree (com.linkedin.data.transform.filter.request.MaskTree)5 ResourceModel (com.linkedin.restli.internal.server.model.ResourceModel)5