Пример #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="WebSocketHandlerBase" /> class.
        /// </summary>
        /// <param name="maxBufferSize">Maximum size of the buffer.</param>
        protected WebSocketHandlerBase(int maxBufferSize, RestApiSettings defaultSettings)
        {
            if (maxBufferSize < 32)
            {
                maxBufferSize = 32;
            }

            this.MaxBufferSize = maxBufferSize;
        }
Пример #2
0
 /// <summary>
 /// Initializes a new instance of the <see cref="RuntimeRoute" /> class.
 /// </summary>
 /// <param name="methodInfo">The method information.</param>
 /// <param name="instanceType">Type of the instance.</param>
 /// <param name="instance">The instance.</param>
 /// <param name="isActionUsed">if set to <c>true</c> [is action used].</param>
 /// <param name="isTokenRequired">if set to <c>true</c> [is token required].</param>
 /// <param name="moduleName">Name of the module.</param>
 /// <param name="setting">The setting.</param>
 /// <param name="permissions">The permissions.</param>
 /// <param name="headerKeys">The header keys.</param>
 public RuntimeRoute(MethodInfo methodInfo, Type instanceType, object instance, bool isActionUsed, bool isTokenRequired, string moduleName, RestApiSettings setting, IDictionary<string, ApiPermission> permissions = null, List<string> headerKeys = null)
 {
     this.MethodInfo = methodInfo;
     this.Instance = instance;
     this.IsActionUsed = isActionUsed;
     this.InstanceType = instanceType;
     this.ModuleName = moduleName;
     this.IsTokenRequired = isTokenRequired;
     this.Setting = setting;
     this.Permissions = permissions;
     this.HeaderKeys = headerKeys;
 }
Пример #3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ApiHandlerBase" /> class.
        /// </summary>
        /// <param name="defaultApiSettings">The default API settings.</param>
        /// <param name="allowOptions">if set to <c>true</c> [allow options].</param>
        protected ApiHandlerBase(RestApiSettings defaultApiSettings, bool allowOptions = false)
        {
            // Ensure it is never null. Default values should be safe.
            DefaultSettings = defaultApiSettings ?? new RestApiSettings
            {
                TokenHeaderKey = HttpConstants.HttpHeader.TOKEN,
                ClientIdentifierHeaderKey = HttpConstants.HttpHeader.CLIENTIDENTIFIER,
                EnableContentCompression = true
            };

            DefaultSettings.Name = DefaultSettings.Name.SafeToString(defaultSettingName);
            DefaultSettings.ApiTracking = DefaultSettings.ApiTracking ?? Framework.ApiTracking;

            settingsContainer.Merge(DefaultSettings.Name, DefaultSettings, false);

            this.AllowOptions = allowOptions;
        }
Пример #4
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ApiHandlerBase" /> class.
        /// </summary>
        /// <param name="defaultApiSettings">The default API settings.</param>
        /// <param name="allowOptions">if set to <c>true</c> [allow options].</param>
        protected ApiHandlerBase(RestApiSettings defaultApiSettings, bool allowOptions = false)
        {
            // Ensure it is never null. Default values should be safe.
            DefaultSettings = defaultApiSettings ?? new RestApiSettings
            {
                TokenHeaderKey = HttpConstants.HttpHeader.TOKEN,
                ClientIdentifierHeaderKey = HttpConstants.HttpHeader.CLIENTIDENTIFIER,
                EnableContentCompression = true,
                TrackingEvent = false,
                EnableOutputFullExceptionInfo = false
            };

            DefaultSettings.Name = DefaultSettings.Name.SafeToString("Default");
            DefaultSettings.ApiTracking = DefaultSettings.ApiTracking ?? DiagnosticFileLogger.CreateOrUpdateDiagnosticFileLogger(DefaultSettings.Name);

            settingsContainer.Merge(DefaultSettings.Name, DefaultSettings, false);

            this.AllowOptions = allowOptions;
        }
Пример #5
0
 /// <summary>
 /// Packages the output. <c>Flush()</c> would be called in this method.
 /// </summary>
 /// <param name="response">The response.</param>
 /// <param name="data">The data.</param>
 /// <param name="baseException">The base exception.</param>
 /// <param name="acceptEncoding">Name of the compress.</param>
 /// <param name="noBody">if set to <c>true</c> [no body].</param>
 /// <param name="settings">The settings.</param>
 /// <returns>System.Object.</returns>
 protected virtual void PackageOutput(HttpResponse response, object data, BaseException baseException = null, string acceptEncoding = null, bool noBody = false, RestApiSettings settings = null)
 {
     PackageResponse(response, data, baseException, acceptEncoding, noBody, settings);
 }
Пример #6
0
        /// <summary>
        /// Packages the response. <c>Flush()</c> would be called in this method.
        /// </summary>
        /// <param name="response">The response.</param>
        /// <param name="data">The data.</param>
        /// <param name="ex">The ex.</param>
        /// <param name="acceptEncoding">The accept encoding.</param>
        /// <param name="noBody">if set to <c>true</c> [no body].</param>
        /// <param name="settings">The settings.</param>
        public static void PackageResponse(HttpResponseBase response, object data, BaseException ex = null, string acceptEncoding = null, bool noBody = false, RestApiSettings settings = null)
        {
            if (response != null)
            {
                if (settings == null)
                {
                    settings = defaultRestApiSettings;
                }

                var objectToReturn = ex != null ? (settings.EnableOutputFullExceptionInfo ? ex.ToExceptionInfo() : new SimpleExceptionInfo
                {
                    Message = ex.Hint != null ? (ex.Hint.Message ?? ex.Hint.Cause) : ex.RootCause.Message,
                    Data = data == null ? null : JObject.FromObject(data),
                    Code = ex.Hint?.Code ?? ex.Code
                } as object) : data;

                response.Headers.Add(HttpConstants.HttpHeader.SERVERNAME, EnvironmentCore.ServerName);
                response.Headers.AddIfNotNull(HttpConstants.HttpHeader.TRACEID, ApiTraceContext.TraceId);

                response.StatusCode = (int)(ex == null ? (noBody ? HttpStatusCode.NoContent : HttpStatusCode.OK) : ex.Code.ToHttpStatusCode());

                if (!noBody)
                {
                    response.ContentType = "application/json";

                    if (settings.EnableContentCompression)
                    {
                        acceptEncoding = acceptEncoding.SafeToString().ToLower();
                        if (acceptEncoding.Contains("gzip"))
                        {
                            response.Filter = new System.IO.Compression.GZipStream(response.Filter,
                                                  System.IO.Compression.CompressionMode.Compress);
                            response.Headers.Remove(HttpConstants.HttpHeader.ContentEncoding);
                            response.AppendHeader(HttpConstants.HttpHeader.ContentEncoding, "gzip");
                        }
                        else if (acceptEncoding.Contains("deflate"))
                        {
                            response.Filter = new System.IO.Compression.DeflateStream(response.Filter,
                                                System.IO.Compression.CompressionMode.Compress);
                            response.Headers.Remove(HttpConstants.HttpHeader.ContentEncoding);
                            response.AppendHeader(HttpConstants.HttpHeader.ContentEncoding, "deflate");
                        }
                    }

                    response.Write(objectToReturn.ToJson(true, JsonConverters));
                }

                response.Headers.Add(HttpConstants.HttpHeader.SERVEREXITTIME, DateTime.UtcNow.ToFullDateTimeTzString());
                response.Flush();
            }
        }
Пример #7
0
 /// <summary>
 /// Packages the response. <c>Flush()</c> would be called in this method.
 /// </summary>
 /// <param name="response">The response.</param>
 /// <param name="data">The data.</param>
 /// <param name="ex">The ex.</param>
 /// <param name="acceptEncoding">Name of the compression.</param>
 /// <param name="noBody">if set to <c>true</c> [no body].</param>
 /// <param name="settings">The settings.</param>
 /// <returns>System.Object.</returns>
 public static void PackageResponse(HttpResponse response, object data, BaseException ex = null, string acceptEncoding = null, bool noBody = false, RestApiSettings settings = null)
 {
     if (response != null)
     {
         PackageResponse(new HttpResponseWrapper(response), data, ex, acceptEncoding, noBody, settings);
     }
 }
Пример #8
0
        /// <summary>
        /// Adds the setting.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="setting">The setting.</param>
        /// <param name="overrideIfExists">The override if exists.</param>
        /// <returns>System.Boolean.</returns>
        public static bool AddSetting(string name, RestApiSettings setting, bool overrideIfExists = false)
        {
            if (setting != null)
            {
                return settingsContainer.Merge(name.SafeToString(), setting, overrideIfExists);
            }

            return false;
        }
Пример #9
0
        /// <summary>
        /// Packages the response. <c>Flush()</c> would be called in this method.
        /// </summary>
        /// <param name="response">The response.</param>
        /// <param name="data">The data.</param>
        /// <param name="ex">The ex.</param>
        /// <param name="acceptEncoding">The accept encoding.</param>
        /// <param name="noBody">if set to <c>true</c> [no body].</param>
        /// <param name="contentType">Type of the content.</param>
        /// <param name="settings">The settings.</param>
        public static void PackageResponse(HttpResponseBase response, object data, BaseException ex = null, string acceptEncoding = null, bool noBody = false, string contentType = null, RestApiSettings settings = null)
        {
            if (response != null)
            {
                if (settings == null)
                {
                    settings = defaultRestApiSettings;
                }

                var objectToReturn = ex != null ? (settings.OmitExceptionDetail ? ex.ToSimpleExceptionInfo() : ex.ToExceptionInfo()) : data;

                response.Headers.Add(HttpConstants.HttpHeader.SERVERNAME, EnvironmentCore.ServerName);
                response.Headers.AddIfNotNullOrEmpty(HttpConstants.HttpHeader.TRACEID, ApiTraceContext.TraceId);

                response.StatusCode = (int)(ex == null ? (noBody ? HttpStatusCode.NoContent : HttpStatusCode.OK) : ex.Code.ToHttpStatusCode());

                if (!noBody)
                {
                    response.ContentType = contentType.SafeToString(HttpConstants.ContentType.Json);

                    if (settings.EnableContentCompression)
                    {
                        acceptEncoding = acceptEncoding.SafeToString().ToLower();
                        if (acceptEncoding.Contains(HttpConstants.HttpValues.GZip))
                        {
                            response.Filter = new System.IO.Compression.GZipStream(response.Filter,
                                                  System.IO.Compression.CompressionMode.Compress);
                            response.Headers.Remove(HttpConstants.HttpHeader.ContentEncoding);
                            response.AppendHeader(HttpConstants.HttpHeader.ContentEncoding, HttpConstants.HttpValues.GZip);
                        }
                        else if (acceptEncoding.Contains("deflate"))
                        {
                            response.Filter = new System.IO.Compression.DeflateStream(response.Filter,
                                                System.IO.Compression.CompressionMode.Compress);
                            response.Headers.Remove(HttpConstants.HttpHeader.ContentEncoding);
                            response.AppendHeader(HttpConstants.HttpHeader.ContentEncoding, "deflate");
                        }
                    }

                    response.Write(objectToReturn.ToJson(true, JsonConverters));
                }

                response.Headers.Add(HttpConstants.HttpHeader.SERVEREXITTIME, DateTime.UtcNow.ToFullDateTimeTzString());
            }
        }
Пример #10
0
 /// <summary>
 /// Adds the handler (instance and settings) into route.
 /// </summary>
 /// <param name="instance">The instance.</param>
 /// <param name="settings">The settings.</param>
 public void Add(object instance, RestApiSettings settings = null)
 {
     InitializeRoute(instance, settings);
 }
Пример #11
0
 /// <summary>
 /// Initializes a new instance of the <see cref="RestApiRouter" /> class.
 /// </summary>
 /// <param name="defaultApiSettings">The default API settings.</param>
 /// <param name="allowOptions">if set to <c>true</c> [allow options].</param>
 public RestApiRouter(RestApiSettings defaultApiSettings, bool allowOptions = false)
     : base(defaultApiSettings, allowOptions)
 {
 }
Пример #12
0
        /// <summary>
        /// Initializes the routes.
        /// </summary>
        /// <param name="instance">The instance.</param>
        /// <param name="settings">The settings.</param>
        /// <exception cref="DataConflictException">Route</exception>
        protected void InitializeRoute(object instance, RestApiSettings settings = null)
        {
            lock (routeOperationLocker)
            {
                if (instance != null)
                {
                    var typeName = instance.GetType().FullName;
                    if (!initializedTypes.Contains(typeName))
                    {
                        #region Initialize routes

                        var doneInterfaceTypes = new List<string>();

                        foreach (var interfaceType in instance.GetType().GetInterfaces())
                        {
                            InitializeApiType(doneInterfaceTypes, routes, interfaceType, instance, settings);
                        }

                        #endregion

                        initializedTypes.Add(typeName);
                    }
                }
            }
        }
Пример #13
0
        /// <summary>
        /// Initializes the type of the API.
        /// </summary>
        /// <param name="doneInterfaceTypes">The done interface types.</param>
        /// <param name="routes">The routes.</param>
        /// <param name="interfaceType">Type of the interface.</param>
        /// <param name="instance">The instance.</param>
        /// <param name="settings">The settings.</param>
        /// <param name="parentApiContractAttribute">The parent API class attribute.</param>
        /// <param name="parentApiModuleAttribute">The parent API module attribute.</param>
        protected void InitializeApiType(List<string> doneInterfaceTypes, Dictionary<string, RuntimeRoute> routes, Type interfaceType, object instance, RestApiSettings settings = null, ApiContractAttribute parentApiContractAttribute = null, ApiModuleAttribute parentApiModuleAttribute = null)
        {
            if (routes != null && interfaceType != null && doneInterfaceTypes != null)
            {
                if (doneInterfaceTypes.Contains(interfaceType.FullName))
                {
                    return;
                }

                var ApiContract = parentApiContractAttribute ?? interfaceType.GetCustomAttribute<ApiContractAttribute>(true);
                var apiModule = parentApiModuleAttribute ?? interfaceType.GetCustomAttribute<ApiModuleAttribute>(true);
                var moduleName = apiModule?.ToString();

                if (ApiContract != null && !string.IsNullOrWhiteSpace(ApiContract.Version))
                {
                    var apiContractName = ApiContract.Name.SafeToString(interfaceType.FullName);

                    if (ApiContract.Version.SafeToLower().Equals(BuildInFeatureVersionKeyword))
                    {
                        throw new InvalidObjectException("ApiContract.Version", reason: "<buildin> cannot be used as version due to it is used internally.");
                    }

                    foreach (var method in interfaceType.GetMethods())
                    {
                        var apiOperationAttribute = method.GetCustomAttribute<ApiOperationAttribute>(true);
                        var apiTransportAttribute = method.GetCustomAttribute<ApiTransportAttribute>();

                        #region Initialize based on ApiOperation

                        if (apiOperationAttribute != null)
                        {
                            var permissions = new Dictionary<string, ApiPermission>();
                            var additionalHeaderKeys = new HashSet<string>();

                            var apiPermissionAttributes =
                                method.GetCustomAttributes<ApiPermissionAttribute>(true);

                            if (apiPermissionAttributes != null)
                            {
                                foreach (var one in apiPermissionAttributes)
                                {
                                    permissions.Merge(one.PermissionIdentifier, one.Permission);
                                }
                            }

                            var headerKeyAttributes = method.GetCustomAttributes<ApiHeaderAttribute>(true);
                            if (headerKeyAttributes != null)
                            {
                                foreach (var one in headerKeyAttributes)
                                {
                                    additionalHeaderKeys.Add(one.HeaderKey);
                                }
                            }

                            var routeKey = GetRouteKey(ApiContract.Version, apiOperationAttribute.ResourceName,
                                apiOperationAttribute.HttpMethod, apiOperationAttribute.Action);

                            RuntimeRoute runtimeRoute = null;

                            if (apiTransportAttribute != null)
                            {
                                runtimeRoute = new RuntimeRoute(apiTransportAttribute);
                            }
                            else
                            {
                                var tokenRequired =
                                    method.GetCustomAttribute<TokenRequiredAttribute>(true) ??
                                    interfaceType.GetCustomAttribute<TokenRequiredAttribute>(true);

                                runtimeRoute = new RuntimeRoute(method, interfaceType, instance,
                                    !string.IsNullOrWhiteSpace(apiOperationAttribute.Action),
                                    tokenRequired != null && tokenRequired.TokenRequired, moduleName, apiContractName, settings, permissions, additionalHeaderKeys.ToList());
                            }

                            if (routes.ContainsKey(routeKey))
                            {
                                throw new DataConflictException("Route", objectIdentity: routeKey, data: new
                                {
                                    existed = routes[routeKey].SafeToString(),
                                    newMethod = method.GetFullName(),
                                    newInterface = interfaceType.FullName
                                });
                            }

                            routes.Add(routeKey, runtimeRoute);
                        }

                        #endregion
                    }

                    foreach (var one in interfaceType.GetInterfaces())
                    {
                        InitializeApiType(doneInterfaceTypes, routes, one, instance, settings, ApiContract, apiModule);
                    }
                }

                doneInterfaceTypes.Add(interfaceType.FullName);
            }
        }
Пример #14
0
        /// <summary>
        /// Initializes the type of the API.
        /// </summary>
        /// <param name="doneInterfaceTypes">The done interface types.</param>
        /// <param name="routes">The routes.</param>
        /// <param name="interfaceType">Type of the interface.</param>
        /// <param name="instance">The instance.</param>
        /// <param name="settings">The settings.</param>
        /// <param name="parentApiContractAttribute">The parent API class attribute.</param>
        /// <param name="parentApiModuleAttribute">The parent API module attribute.</param>
        protected void InitializeApiType(List<string> doneInterfaceTypes, Dictionary<string, RuntimeRoute> routes, Type interfaceType, object instance, RestApiSettings settings = null, ApiContractAttribute parentApiContractAttribute = null, ApiModuleAttribute parentApiModuleAttribute = null)
        {
            if (routes != null && interfaceType != null && doneInterfaceTypes != null)
            {
                if (doneInterfaceTypes.Contains(interfaceType.FullName))
                {
                    return;
                }

                var apiContract = parentApiContractAttribute ?? interfaceType.GetCustomAttribute<ApiContractAttribute>(true);
                var apiModule = parentApiModuleAttribute ?? interfaceType.GetCustomAttribute<ApiModuleAttribute>(true);
                var moduleName = apiModule?.ToString();

                if (apiContract != null && !string.IsNullOrWhiteSpace(apiContract.Version))
                {
                    if (apiContract.Version.SafeToLower().Equals(BuiltInFeatureVersionKeyword))
                    {
                        throw ExceptionFactory.CreateInvalidObjectException("apiContract.Version", reason: "<builtin> cannot be used as version due to it is used internally.");
                    }

                    foreach (var method in interfaceType.GetMethods())
                    {
                        var apiOperationAttribute = method.GetCustomAttribute<ApiOperationAttribute>(true);

                        #region Initialize based on ApiOperation

                        if (apiOperationAttribute != null)
                        {
                            var permissions = new Dictionary<string, ApiPermission>();
                            var additionalHeaderKeys = new HashSet<string>();

                            var apiPermissionAttributes =
                                method.GetCustomAttributes<ApiPermissionAttribute>(true);

                            if (apiPermissionAttributes != null)
                            {
                                foreach (var one in apiPermissionAttributes)
                                {
                                    permissions.Merge(one.PermissionIdentifier, one.Permission);
                                }
                            }

                            var headerKeyAttributes = method.GetCustomAttributes<ApiHeaderAttribute>(true);
                            if (headerKeyAttributes != null)
                            {
                                foreach (var one in headerKeyAttributes)
                                {
                                    additionalHeaderKeys.Add(one.HeaderKey);
                                }
                            }

                            var routeKey = GetRouteKey(apiContract.Version, apiOperationAttribute.ResourceName,
                                apiOperationAttribute.HttpMethod, apiOperationAttribute.Action);

                            var tokenRequired =
                                method.GetCustomAttribute<TokenRequiredAttribute>(true) ??
                                interfaceType.GetCustomAttribute<TokenRequiredAttribute>(true);

                            var runtimeRoute = new RuntimeRoute(method, interfaceType, instance,
                                   !string.IsNullOrWhiteSpace(apiOperationAttribute.Action),
                                   tokenRequired != null && tokenRequired.TokenRequired, moduleName, settings, permissions, additionalHeaderKeys.ToList());

                            if (routes.ContainsKey(routeKey))
                            {
                                throw new DataConflictException("Route", objectIdentity: routeKey, data: new
                                {
                                    existed = routes[routeKey].SafeToString(),
                                    newMethod = method.GetFullName(),
                                    newInterface = interfaceType.FullName
                                });
                            }

                            routes.Add(routeKey, runtimeRoute);
                        }

                        #endregion
                    }

                    foreach (var one in interfaceType.GetInterfaces())
                    {
                        InitializeApiType(doneInterfaceTypes, routes, one, instance, settings, apiContract, apiModule);
                    }

                    //Special NOTE:
                    // Move this add action in scope of if apiContract is valid.
                    // Reason: in complicated cases, when [A:Interface1] without ApiContract, but [Interface2: Interface] with defining ApiContract, and [B: A, Interface2], then correct contract definition might be missed.
                    doneInterfaceTypes.Add(interfaceType.FullName);
                }

            }
        }
Пример #15
0
 /// <summary>
 /// Initializes a new instance of the <see cref="SecuredApiRouter"/> class.
 /// </summary>
 /// <param name="defaultApiSettings">The default API settings.</param>
 public SecuredApiRouter(RestApiSettings defaultApiSettings)
     : base(defaultApiSettings, false)
 {
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="RestApiContextConsistenceAttribute"/> class.
 /// </summary>
 /// <param name="restApiSetting">The rest API settings.</param>
 public RestApiContextConsistenceAttribute(RestApiSettings restApiSetting)
     : base()
 {
     this.settings = restApiSetting;
     ApiTracking = restApiSetting?.ApiTracking;
 }