コード例 #1
0
        /// <summary>
        /// Processes the build in feature.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="runtimeContext">The runtime context.</param>
        /// <param name="isLocalhost">The is localhost.</param>
        /// <param name="contentType">Type of the content.</param>
        /// <returns>
        /// System.Object.
        /// </returns>
        protected override object ProcessBuiltInFeature(HttpApiContextContainer <TRequest, TResponse> context, RuntimeContext runtimeContext, bool isLocalhost, out string contentType)
        {
            object result = null;

            contentType = HttpConstants.ContentType.Json;

            switch ((runtimeContext?.ResourceName).SafeToString().ToLowerInvariant())
            {
            case "apilist":
                result = RestApiRoutePool.Routes.Select(x => new
                {
                    Url           = x.Key.ToRoutePath(true),
                    TokenRequired = x.Value?.OperationParameters?.IsTokenRequired
                }).ToList();
                break;

            case "configuration":
                result = isLocalhost ? Framework.ConfigurationValues : localhostTip as object;
                break;

            case "doc":
            case "doc.zip":
                result = ApiRouterExtensionFeature.DocumentatGeneration;

                DocumentGenerator generator = new DocumentGenerator(RestApiSettingPool.DefaultRestApiSettings?.TokenHeaderKey.SafeToString(HttpConstants.HttpHeader.TOKEN));
                result = generator.WriteHtmlDocumentToZipByRoutes((from item in RestApiRoutePool.Routes select item.Value).Distinct().ToArray());
                if (result != null)
                {
                    contentType = HttpConstants.ContentType.ZipFile;
                }
                break;

            default: break;
            }

            return(result ?? base.ProcessBuiltInFeature(context, runtimeContext, isLocalhost, out contentType));
        }
コード例 #2
0
        /// <summary>
        /// Enables processing of HTTP Web requests by a custom HttpHandler that implements the <see cref="T:System.Web.IHttpHandler" /> interface.
        /// </summary>
        /// <param name="context">An <see cref="T:System.Web.HttpContext" /> object that provides references to the intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests.</param>
        public void ProcessHttpApiContextContainer(HttpApiContextContainer <TRequest, TResponse> context)
        {
            context.EntryStamp = DateTime.UtcNow;
            context.SetResponseHeader(HttpConstants.HttpHeader.SERVERENTRYTIME, context.EntryStamp.ToFullDateTimeTzString());

            var acceptEncoding = context.TryGetRequestHeader(HttpConstants.HttpHeader.AcceptEncoding);

            try
            {
                //First of all, clean thread info for context.
                ContextHelper.Reinitialize();

                context.TraceId       = context.TryGetRequestHeader(HttpConstants.HttpHeader.TRACEID);
                context.TraceSequence = context.TryGetRequestHeader(HttpConstants.HttpHeader.TRACESEQUENCE).ToNullableInt32();

                Prepare(context.Request);

                if (context.HttpMethod.Equals(HttpConstants.HttpMethod.Options, StringComparison.OrdinalIgnoreCase))
                {
                    if (AllowOptions)
                    {
                        //Return directly. IIS would append following headers by default, according to what exactly web.config have.
                        //Access-Control-Allow-Origin: *
                        //Access-Control-Allow-Headers: Content-Type
                        //Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS

                        context.SetResponseHeader(HttpConstants.HttpHeader.SERVEREXITTIME, DateTime.UtcNow.ToFullDateTimeTzString());

                        return;
                    }
                }

                // Authentication has already done inside ProcessRoute.
                var runtimeContext = ProcessRoute(context);
                runtimeContext.CheckNullObject(nameof(runtimeContext));
                context.RuntimeContext = runtimeContext;

                // Fill basic context info.

                var userAgentHeaderKey = context.Settings?.OriginalUserAgentHeaderKey;

                //ContextHelper.ConsistContext(
                //    // TOKEN
                //    context.TryGetRequestHeader((context.Settings?.TokenHeaderKey).SafeToString(HttpConstants.HttpHeader.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()),
                //     runtimeContext.ApiRouterIdentifier
                //    );

                if (runtimeContext.OperationParameters?.EntitySynchronizationMode != null)
                {
                    ContextHelper.ApiContext.LastSynchronizedStamp = context.TryGetRequestHeader(runtimeContext.OperationParameters.EntitySynchronizationMode.IfModifiedSinceKey).ObjectToDateTime();
                }

                // Fill finished.
                if (string.IsNullOrWhiteSpace(runtimeContext.Realm) && runtimeContext.Version.Equals(ApiConstants.BuiltInFeatureVersionKeyword, StringComparison.OrdinalIgnoreCase))
                {
                    string contentType;
                    var    buildInResult = ProcessBuiltInFeature(context, runtimeContext, context.IsLocal, out contentType);
                    PackageResponse(context, buildInResult, new RuntimeApiOperationParameters {
                        ContentType = contentType
                    }, null, acceptEncoding, runtimeContext.IsVoid ?? false, context.Settings);
                }
                else
                {
                    //Initialize additional header keys
                    if ((runtimeContext.OperationParameters?.CustomizedHeaderKeys).HasItem())
                    {
                        var currentApiContext = ContextHelper.ApiContext;

                        foreach (var one in runtimeContext.OperationParameters.CustomizedHeaderKeys)
                        {
                            currentApiContext.CustomizedHeaders.Merge(one, context.TryGetRequestHeader(one));
                        }
                    }

                    InitializeContext(context.Request, runtimeContext);

                    byte[] body = context.ReadRequestBody();
                    context.CollectTrackingInfo(body.LongLength);

                    if (runtimeContext.Exception != null)
                    {
                        throw runtimeContext.Exception;
                    }

                    ApiTraceContext.Enter(runtimeContext, setNameAsMajor: true);
                    string jsonBody = null;

                    try
                    {
                        if (runtimeContext.ApiCacheStatus == ApiCacheStatus.UseCache)
                        {
                            jsonBody = runtimeContext.CachedResponseBody;
                        }
                        else
                        {
                            var invokeResult = Invoke(runtimeContext.ApiInstance, runtimeContext.ApiMethod, context, runtimeContext.EntityKey, out jsonBody);

                            if (runtimeContext.ApiCacheStatus == ApiCacheStatus.UpdateCache)
                            {
                                runtimeContext.ApiCacheContainer.Update(runtimeContext.ApiCacheIdentity, jsonBody);
                            }

                            PackageResponse(context, invokeResult, runtimeContext.OperationParameters, null, acceptEncoding, runtimeContext.IsVoid ?? false, settings: context.Settings);
                        }
                    }
                    catch (Exception invokeEx)
                    {
                        context.BaseException = invokeEx.Handle(new { Url = context.RawUrl, Method = context.HttpMethod });
                        throw context.BaseException;
                    }
                    finally
                    {
                        ApiTraceContext.Exit(context.BaseException?.Key);
                    }
                }
            }
            catch (Exception ex)
            {
                var apiTracking = context.Settings?.ApiTracking;
                context.BaseException = (ex as BaseException) ?? ex.Handle(new { Uri = context.Url.SafeToString() });

                (apiTracking ?? Framework.ApiTracking)?.LogException(context.BaseException.ToExceptionInfo(eventKey: context.ApiEvent?.Key.SafeToString()));

                if (context.ApiEvent != null)
                {
                    context.ApiEvent.ExceptionKey = context.BaseException.Key;
                }

                PackageResponse(context, null, null, context.BaseException, acceptEncoding, settings: context.Settings);
            }
            finally
            {
                if (context.Settings?.ApiTracking != null)
                {
                    var exitStamp = DateTime.UtcNow;
                    if (context.ApiEvent != null)
                    {
                        try
                        {
                            context.ApiEvent.ExitStamp = exitStamp;
                            context.Settings.ApiTracking.LogApiEvent(context.ApiEvent);
                        }
                        catch { }
                    }

                    if (ApiTraceContext.Root != null)
                    {
                        try
                        {
                            ApiTraceContext.Exit(context.BaseException?.Key, exitStamp);
                            context.Settings.ApiTracking.LogApiTraceLog(ApiTraceContext.GetCurrentTraceLog(true));
                        }
                        catch { }
                    }
                }

                Dispose();
            }
        }
コード例 #3
0
 /// <summary>
 /// Invokes the specified method information.
 /// <remarks>
 /// Invoke action would regard to method parameter to use difference logic. Following steps show the IF-ELSE case. When it is hit, other would not go through.
 /// <list type="number"><item>
 /// If input parameter count is 0, invoke without parameter object.
 /// </item><item>
 /// If input parameter count is 1 and key is not empty or null, invoke using key.
 /// </item><item>
 /// If input parameter count is 1 and key is empty or null, invoke using key, try to get JSON object from request body and convert to object for invoke.
 /// </item><item>
 /// If input parameter count more than 1, try read JSON data to match parameters by name (ignore case) in root level, then invoke.
 /// </item></list></remarks></summary>
 protected virtual object Invoke(object instance, MethodInfo methodInfo, HttpApiContextContainer <TRequest, TResponse> context, string key, out string jsonBody)
 {
     return(InternalInvoke(instance, methodInfo, context.ReadRequestBody(), context.Url, key, out jsonBody));
 }
コード例 #4
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();
            }
        }
コード例 #5
0
        /// <summary>
        /// Processes the built in feature.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="runtimeContext">The runtime context.</param>
        /// <param name="isLocalhost">if set to <c>true</c> [is localhost].</param>
        /// <param name="contentType">Type of the content.</param>
        /// <returns></returns>
        protected virtual object ProcessBuiltInFeature(HttpApiContextContainer <TRequest, TResponse> context, RuntimeContext runtimeContext, bool isLocalhost, out string contentType)
        {
            object result = null;

            contentType = HttpConstants.ContentType.Json;

            switch (runtimeContext?.ResourceName.SafeToLower())
            {
            case "server":
                result = Framework.AboutService();
                break;

            case "psk":    //public secured key
                result = Framework.AboutService();
                break;

            case "configuration":
                result = isLocalhost ? Framework.ConfigurationValues : localhostTip as object;
                break;

            case "machine":
                result = SystemManagementExtension.GetMachineHealth();
                break;

            case "cache":
                result = CacheRealm.GetSummary();
                break;

            case "clearmemorycache":
                if (isLocalhost)
                {
                    CacheRealm.ClearAll();
                    result = "Done.";
                }
                else
                {
                    result = "This API is available at localhost machine.";
                }
                break;

            case "gravity":
                result =     //Gravity.GravityShell.Current?.Info;
                         "<Retired>";
                break;

            case "i18n":
                result = Framework.GetGlobalResourceAvailableCultureInfo() ?? new Collection <CultureInfo>();
                break;

            case "mirror":
                var apiContext = ContextHelper.ApiContext;
                var headers    = new Dictionary <string, string>();

                foreach (var key in context.RequestAllHeaderKeys)
                {
                    headers.Add(key, context.TryGetRequestHeader(key));
                }

                result = new
                {
                    RawUrl      = context.RawUrl,
                    HttpMethod  = context.HttpMethod,
                    Headers     = headers,
                    UserAgent   = apiContext.UserAgent,
                    IpAddress   = apiContext.IpAddress,
                    CultureCode = apiContext.CultureCode
                };
                break;

            case "assemblyhash":
                result = EnvironmentCore.GetAssemblyHash();
                break;

            case "dll":
                var dllName = context.QueryString.Get("name");
                if (!string.IsNullOrWhiteSpace(dllName) && context.HttpMethod.MeaningfulEquals(HttpConstants.HttpMethod.Post, StringComparison.OrdinalIgnoreCase))
                {
                    try
                    {
                        var dllPath = Path.Combine(EnvironmentCore.ApplicationBaseDirectory, dllName + ".dll");
                        if (File.Exists(dllPath))
                        {
                            result      = File.ReadAllBytes(dllPath);
                            contentType = HttpConstants.ContentType.BinaryDefault;
                        }
                    }
                    catch { }
                }
                break;

            default:
                break;
            }

            return(result);
        }