Skip to content
This repository has been archived by the owner on Nov 1, 2023. It is now read-only.

Loading client policies dynamically #48

Open
sakopov opened this issue Jan 25, 2016 · 1 comment
Open

Loading client policies dynamically #48

sakopov opened this issue Jan 25, 2016 · 1 comment

Comments

@sakopov
Copy link

sakopov commented Jan 25, 2016

I'm trying to figure out if there is a better way to load client policies w/o loading all of them on startup. I can load all via IThrottlePolicyProvider, but I think as the number of clients grows it would be bit on the heavy side.

So far I've tried creating a middleware to read api key from Authorization-Token header and do a lookup on it to find the client and their rate limits stored in a database. I then store client's rate limits in OWIN context so it can be accessed later on.

        public override async Task Invoke(IOwinContext context)
        {
            var headers = context.Request.Headers;

            if (headers != null && headers.Any(header => header.Key.Equals("Authorization-Token")))
            {
                var apiKey = headers
                    .FirstOrDefault(pair => pair.Key.Equals("Authorization-Token"))
                    .Value
                    .FirstOrDefault();

                var client = await _clientsRetriever.GetByApiKey(apiKey);

                if (client != null)
                {
                    context.Set("client.AuthorizationToken", apiKey);
                    context.Set("client.RateLimits", new RateLimits
                    {
                        PerWeek = client.RateLimits.RequestsPerWeek ?? 0,
                        PerDay = client.RateLimits.RequestsPerDay ?? 0,
                        PerMinute = client.RateLimits.RequestsPerMinute ?? 0,
                        PerHour = client.RateLimits.RequestsPerHour ?? 0,
                        PerSecond = client.RateLimits.RequestsPerSecond ?? 0
                    });
                }
            }

            await Next.Invoke(context);
        }

I then implemented IPolicyRepository.FirstOrDefault which appears to be getting called for all requests. Here, I'm basically returning ThrottlePolicy with the rate limits for the current client in OWIN context only.

        public ThrottlePolicy FirstOrDefault(string id)
        {
            var token = HttpContext.Current.GetOwinContext().Get<string>("client.AuthorizationToken");
            var rateLimit = HttpContext.Current.GetOwinContext().Get<RateLimits>("client.RateLimits");

            var throttlePolicy = new ThrottlePolicy(perSecond: 0, perMinute: 0, perHour: 0, perDay: 0, perWeek: 0)
            {
                ClientThrottling = true
            };

            if (rateLimit != null)
            {
                throttlePolicy.ClientRules.Add(token, rateLimit);
            }

            return throttlePolicy;
        }

I'm not showing all of the code, but in general this works ok. Howevert, a little cumbersome and I feel like I may be missing a feature in the library. Any suggestions?

@dmarlow
Copy link
Contributor

dmarlow commented Jul 24, 2017

I too am interested in this. I'd like to have things data-driven so as to be able to change things dynamically without having to re-deploy. Any suggestions for best practice on this would be appreciated.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants