Ejemplo n.º 1
0
        /// <summary>
        /// Processes the route.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="doAuthentication">if set to <c>true</c> [do authentication].</param>
        /// <returns></returns>
        /// <exception cref="ResourceNotFoundException">
        /// ResourceName
        /// or
        /// or
        /// </exception>
        internal virtual RuntimeContext ProcessRoute(HttpApiContextContainer <TRequest, TResponse> context, bool doAuthentication = true)
        {
            try
            {
                context.CheckNullObject(nameof(context));
                var httpMethod = context.HttpMethod;
                var uri        = context.Url;

                var rawFullUrl = string.Format("{0}: {1}", httpMethod, context.Url);
                var result     = InitializeRuntimeContext(uri);

                result.CheckNullObjectAsInvalid("URL");

                if (result.Version.Equals(ApiConstants.BuiltInFeatureVersionKeyword, StringComparison.OrdinalIgnoreCase))
                {
                    return(result);
                }

                if (string.IsNullOrWhiteSpace(result.ResourceName))
                {
                    throw new ResourceNotFoundException(rawFullUrl, nameof(result.ResourceName));
                }

                RuntimeRoute runtimeRoute;
                var          apiRouterIdentifier = new ApiRouteIdentifier(result.Realm, result.Version, result.ResourceName, httpMethod, result.Parameter1);
                if (!RestApiRoutePool.Routes.TryGetValue(apiRouterIdentifier, out runtimeRoute))
                {
                    apiRouterIdentifier = new ApiRouteIdentifier(result.Realm, result.Version, result.ResourceName, httpMethod, null);
                    RestApiRoutePool.Routes.TryGetValue(apiRouterIdentifier, out runtimeRoute);
                }
                else
                {
                    if (runtimeRoute != null && (!string.IsNullOrWhiteSpace(result.Parameter1) && !runtimeRoute.IsActionUsed))
                    {
                        throw new ResourceNotFoundException(rawFullUrl);
                    }
                }

                if (runtimeRoute == null)
                {
                    throw new ResourceNotFoundException(rawFullUrl);
                }

                result.ApiRouterIdentifier = apiRouterIdentifier;

                // Override out parameters
                result.OperationParameters = runtimeRoute.OperationParameters ?? new RuntimeApiOperationParameters();

                result.ApiMethod    = runtimeRoute.ApiMethod;
                result.ApiInstance  = runtimeRoute.ApiInstance;
                result.IsActionUsed = runtimeRoute.IsActionUsed;
                result.IsVoid       = runtimeRoute.IsVoid;
                context.Settings    = result.Settings = runtimeRoute.Setting ?? RestApiSettingPool.DefaultRestApiSettings;
                result.OmitApiEvent = runtimeRoute.OmitApiTracking?.Omit(ApiTrackingType.Event) ?? false;

                if (runtimeRoute.ApiCacheAttribute != null)
                {
                    result.ApiCacheIdentity = runtimeRoute.ApiRouteIdentifier.Clone() as ApiRouteIdentifier;
                    if (runtimeRoute.ApiCacheAttribute.CacheParameter.CachedByParameterizedIdentity)
                    {
                        result.ApiCacheIdentity.SetParameterizedIdentifier(uri.ToQueryString());
                    }

                    result.ApiCacheContainer = runtimeRoute.ApiCacheContainer;

                    if (result.ApiCacheContainer != null)
                    {
                        string cachedResponseBody;
                        if (result.ApiCacheContainer.GetCacheResult(result.ApiCacheIdentity, out cachedResponseBody))
                        {
                            result.CachedResponseBody = cachedResponseBody;
                            result.ApiCacheStatus     = ApiCacheStatus.UseCache;
                        }
                        else
                        {
                            result.ApiCacheStatus = ApiCacheStatus.UpdateCache;
                        }
                    }
                    else
                    {
                        result.ApiCacheStatus = ApiCacheStatus.NoCache;
                    }
                }

                // Fill basic context info.
                var userAgentHeaderKey = context.Settings?.OriginalUserAgentHeaderKey;
                var token = context.TryGetRequestHeader((context.Settings?.TokenHeaderKey).SafeToString(HttpConstants.HttpHeader.TOKEN));
                ContextHelper.ApiContext.IndicatedOperator = context.TryGetRequestHeader(HttpConstants.HttpHeader.OPERATOR);

                ContextHelper.ConsistContext(
                    // TOKEN
                    token,
                    // Settings
                    context.Settings,
                    // IP Address
                    context.TryGetRequestHeader(context.Settings?.OriginalIpAddressHeaderKey.SafeToString(HttpConstants.HttpHeader.ORIGINAL)).SafeToString(context.ClientIpAddress),
                    // User Agent
                    string.IsNullOrWhiteSpace(userAgentHeaderKey) ? context.UserAgent : context.TryGetRequestHeader(userAgentHeaderKey).SafeToString(context.UserAgent),
                    // Culture Code
                    context.QueryString.Get(HttpConstants.QueryString.Language).SafeToString(context.UserLanguages.SafeFirstOrDefault()).EnsureCultureCode(),
                    // Current Uri
                    context.Url,
                    HttpExtension.GetBasicAuthentication(context.TryGetRequestHeader(HttpConstants.HttpHeader.Authorization).DecodeBase64()),
                    apiRouterIdentifier.ToApiUniqueIdentifier()
                    );

                string userIdentifier = ContextHelper.ApiContext.CurrentCredential?.Name.SafeToString(token);

                var authenticationException = doAuthentication ? Authorize(runtimeRoute, ContextHelper.ApiContext) : null;

                if (authenticationException != null)
                {
                    throw authenticationException.Handle(new { result.ApiMethod.Name, token });
                }

                return(result);
            }
            catch (Exception ex)
            {
                throw ex.Handle();
            }
        }
        /// <summary>
        /// Called by the ASP.NET MVC framework before the action method executes.
        /// </summary>
        /// <param name="filterContext">The filter context.</param>
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            base.OnActionExecuting(filterContext);

            IsOptions = HandleOptionsRequests(filterContext);

            if (Depth < 1)
            {
                Depth = 0;
                ContextHelper.Reinitialize();

                DateTime entryStamp = DateTime.UtcNow;
                var      request    = filterContext.HttpContext.Request;

                var traceId       = request.TryGetHeader(HttpConstants.HttpHeader.TRACEID);
                var traceSequence = request.TryGetHeader(HttpConstants.HttpHeader.TRACESEQUENCE).ObjectToNullableInt32();
                var methodInfo    = (filterContext.ActionDescriptor as ReflectedActionDescriptor)?.MethodInfo;

                var httpContextContainer = new HttpBaseApiContextContainer(request, filterContext.HttpContext.Response);
                ContextHelper.ConsistContext(httpContextContainer, settings);

                WebThreadPool.Register();

                if (!string.IsNullOrWhiteSpace(traceId))
                {
                    ApiTraceContext.Initialize(traceId, traceSequence, entryStamp);
                }

                if (settings != null && settings.TrackingEvent)
                {
                    var context = filterContext.HttpContext;
                    ApiEvent = new ApiEventLog
                    {
                        RawUrl     = context.Request.RawUrl,
                        EntryStamp = entryStamp,
                        TraceId    = traceId,
                        // If request came from ApiTransport or other proxy ways, ORIGINAL stands for the IP ADDRESS from original requester.
                        IpAddress          = context.Request.TryGetHeader(settings?.OriginalIpAddressHeaderKey.SafeToString(HttpConstants.HttpHeader.ORIGINAL)).SafeToString(context.Request.UserHostAddress),
                        CultureCode        = ContextHelper.ApiContext.CultureCode,
                        ContentLength      = context.Request.ContentLength,
                        OperatorCredential = ContextHelper.CurrentCredential as BaseCredential,
                        ServerIdentifier   = EnvironmentCore.MachineName,
                        ServiceIdentifier  = EnvironmentCore.ProductName
                    };
                }

                var controllerType = methodInfo?.DeclaringType;

                var tokenRequiredAttribute = methodInfo?.GetCustomAttribute <TokenRequiredAttribute>(true) ?? controllerType?.GetCustomAttribute <TokenRequiredAttribute>(true);
                var permissionAttributes   = controllerType?.GetCustomAttributes <ApiPermissionAttribute>(true).ToDictionary();
                permissionAttributes.Merge(methodInfo?.GetCustomAttributes <ApiPermissionAttribute>(true).ToDictionary(), true);

                var tokenRequired = tokenRequiredAttribute != null && tokenRequiredAttribute.TokenRequired;

                if (tokenRequired)
                {
                    if (ContextHelper.CurrentCredential == null)
                    {
                        var baseException = (new UnauthorizedTokenException(ContextHelper.Token)).Handle(
                            filterContext.HttpContext.Request.ToExceptionScene(filterContext.RouteData?.GetControllerName()), data: new { filterContext.HttpContext.Request.RawUrl });

                        HandleUnauthorizedAction(filterContext, baseException);
                    }
                    else if (permissionAttributes.HasItem())
                    {
                        var baseException = ContextHelper.CurrentUserInfo?.Permissions.ValidateApiPermission(permissionAttributes, ContextHelper.Token, methodInfo?.GetFullName());

                        if (baseException != null)
                        {
                            HandleUnauthorizedAction(filterContext, baseException);
                        }
                    }
                }

                ApiTraceContext.Enter(methodInfo.GetFullName(), setNameAsMajor: true);
            }

            Depth++;
        }