예제 #1
0
        /// <summary>
        /// Получает объект кэша по token
        /// </summary>
        /// Если объект не доступен в кэше.
        /// Объект будет загружен из базы, и помещен в кэш.
        /// <param name="guid">Токен клиента</param>
        /// <returns>Объект кэша</returns>
        public MorpherCacheObject GetQueryLimit(Guid guid)
        {
            object obj = _morpherCache.Get(guid.ToString().ToLowerInvariant());

            if (obj != null)
            {
                return((MorpherCacheObject)obj);
            }

            // Если объекта нет в кэше, нужно проверить его в бд.
            MorpherCacheObject morpherCacheObject = _morpherDatabase.GetUserLimits(guid);

            if (morpherCacheObject == null)
            {
                return(null);
            }

            if (morpherCacheObject.Unlimited)
            {
                morpherCacheObject.QueriesLeft = 1000;
            }

            _morpherCache.Set(guid.ToString().ToLowerInvariant(), morpherCacheObject, _absoluteExpiration);
            return(morpherCacheObject);
        }
예제 #2
0
        public void Log(IOwinContext context)
        {
            string remoteAddress = context.Request.RemoteIpAddress;
            string queryString   = HttpUtility.UrlDecode(context.Request.QueryString.ToString());
            string urlPath       = context.Request.Path.ToString();
            string userAgent     = context.Request.Headers.Get("User-Agent");
            int    errorCode;

            int.TryParse(context.Response.Headers.Get("Error-code"), out errorCode);

            Guid?token = null;
            MorpherCacheObject cacheObject = null;

            if (errorCode != new InvalidTokenFormatException().Code)
            {
                token = context.Request.GetToken();

                if (token != null)
                {
                    cacheObject = (MorpherCacheObject)_morpherCache.Get(token.ToString().ToLowerInvariant());
                }
            }

            _logQueue.Enqueue(
                new LogEntity(remoteAddress, queryString, urlPath, DateTime.UtcNow, token, cacheObject?.UserId, userAgent, errorCode));
        }
예제 #3
0
        /// <summary>
        /// Получает объет кэша по ip.
        /// </summary>
        /// <param name="ip">ip клиента</param>
        /// <returns>Запись в кэше; Если ip заблокирован - значение null.</returns>
        public MorpherCacheObject GetQueryLimit(string ip)
        {
            object cache = _morpherCache.Get(ip);

            if (cache != null)
            {
                return((MorpherCacheObject)cache);
            }

            if (_morpherDatabase.IsIpBlocked(ip))
            {
                return(null);
            }

            int limit = _morpherDatabase.GetDefaultDailyQueryLimit();

            // Записываем  объект в кэш.
            MorpherCacheObject morpherCacheObject = new MorpherCacheObject()
            {
                QueriesLeft = limit, PaidUser = false, Unlimited = false
            };

            _morpherCache.Set(ip, morpherCacheObject, _absoluteExpiration);

            return(morpherCacheObject);
        }
예제 #4
0
        public HttpResponseMessage QueriesLeftToday(ResponseFormat?format = null)
        {
            var guid = Request.GetToken();

            MorpherCacheObject cacheObject = null;

            if (guid == null)
            {
                cacheObject = _apiThrottler.GetQueryLimit(Request.GetClientIp());

                if (cacheObject == null)
                {
                    return(Request.CreateResponse(
                               HttpStatusCode.OK,
                               new ServiceErrorMessage(new IpBlockedException()),
                               format));
                }
            }
            else
            {
                cacheObject = _apiThrottler.GetQueryLimit(guid.Value);

                if (cacheObject == null)
                {
                    return(Request.CreateResponse(
                               HttpStatusCode.OK,
                               new ServiceErrorMessage(new TokenNotFoundException()),
                               format));
                }
            }

            return(Request.CreateResponse(HttpStatusCode.OK, Math.Max(cacheObject.QueriesLeft, 0), format));
        }
예제 #5
0
        /// <summary>
        /// Выполняет тарификацию по IP адресу
        /// </summary>
        /// <param name="ip">ip адрес клиента</param>
        /// <returns>Результат тарификации</returns>
        public ApiThrottlingResult Throttle(string ip, int cost)
        {
            MorpherCacheObject morpherCacheObject = GetQueryLimit(ip);

            // Если GetQueryLimit вернул null, значит IP адрес помечен в бд как Blocked
            if (morpherCacheObject == null)
            {
                return(ApiThrottlingResult.IpBlocked);
            }

            return(Charge(morpherCacheObject, cost));
        }
예제 #6
0
        /// <summary>
        /// Выполняет тарификацию по токену
        /// </summary>
        /// <param name="guid">Токен клиента</param>
        /// <returns>Результат тарификации</returns>
        public ApiThrottlingResult Throttle(Guid guid, int cost)
        {
            MorpherCacheObject morpherCacheObject = GetQueryLimit(guid);

            // Если morpherCacheObject null, то токен не был найден в кэше, или бд.
            if (morpherCacheObject == null)
            {
                return(ApiThrottlingResult.TokenNotFound);
            }

            if (morpherCacheObject.Unlimited)
            {
                return(ApiThrottlingResult.Success);
            }

            return(Charge(morpherCacheObject, cost));
        }
예제 #7
0
 static ApiThrottlingResult Charge(MorpherCacheObject morpherCacheObject, int cost)
 {
     return(Interlocked.Add(ref morpherCacheObject.QueriesLeft, -cost) >= 0
         ? ApiThrottlingResult.Success
         : ApiThrottlingResult.Overlimit);
 }