private ThrottleLogEntry ComputeLogEntry(string requestId, RequestIndentity identity, ThrottleCounter throttleCounter, string rateLimitPeriod, long rateLimit)
 {
     return new ThrottleLogEntry
             {
                 ClientIp = identity.ClientIp,
                 ClientKey = identity.ClientKey,
                 Endpoint = identity.Endpoint,
                 LogDate = DateTime.UtcNow,
                 RateLimit = rateLimit,
                 RateLimitPeriod = rateLimitPeriod,
                 RequestId = requestId,
                 StartPeriod = throttleCounter.Timestamp,
                 TotalRequests = throttleCounter.TotalRequests
             };
 }
        private ThrottleCounter ProcessRequest(ThrottlePolicy throttlePolicy, RequestIndentity throttleEntry, TimeSpan timeSpan, RateLimitPeriod period, out string id)
        {
            var throttleCounter = new ThrottleCounter();
            throttleCounter.Timestamp = DateTime.UtcNow;
            throttleCounter.TotalRequests = 1;

            //computed request unique id from IP, client key, url and period
            id = "throttle";

            if (throttlePolicy.IpThrottling)
            {
                if (throttlePolicy.IpWhitelist != null && throttlePolicy.IpWhitelist.Contains(throttleEntry.ClientIp))
                {
                    return throttleCounter;
                }

                id += "_" + throttleEntry.ClientIp;
            }

            if (throttlePolicy.ClientThrottling)
            {
                if (throttlePolicy.ClientWhitelist != null && throttlePolicy.ClientWhitelist.Contains(throttleEntry.ClientKey))
                {
                    return throttleCounter;
                }

                id += "_" + throttleEntry.ClientKey;
            }

            if (throttlePolicy.EndpointThrottling)
            {
                if (throttlePolicy.EndpointWhitelist != null && Policy.EndpointWhitelist.Any(x => throttleEntry.Endpoint.Contains(x)))
                {
                    return throttleCounter;
                }

                id += "_" + throttleEntry.Endpoint;
            }

            id += "_" + period;

            //get the hash value of the computed id
            var hashId = ComputeHash(id);

            //serial reads and writes
            lock (_processLocker)
            {
                var entry = Repository.FirstOrDefault(hashId);
                if (entry.HasValue)
                {
                    //entry has not expired
                    if (entry.Value.Timestamp + timeSpan >= DateTime.UtcNow)
                    {
                        //increment request count
                        var totalRequests = entry.Value.TotalRequests + 1;

                        //deep copy
                        throttleCounter = new ThrottleCounter
                        {
                            Timestamp = entry.Value.Timestamp,
                            TotalRequests = totalRequests
                        };

                    }
                }

                //stores: id (string) - timestamp (datetime) - total (long)
                Repository.Save(hashId, throttleCounter, timeSpan);
            }

            return throttleCounter;
        }
        protected virtual RequestIndentity SetIndentity(HttpRequestMessage request)
        {
            var entry = new RequestIndentity();
            entry.ClientIp = GetClientIp(request).ToString();
            entry.Endpoint = request.RequestUri.AbsolutePath;

            entry.ClientKey = request.Headers.Contains("Authorization-Token") ? request.Headers.GetValues("Authorization-Token").First() : "anon";

            return entry;
        }