AspNetCoreRateLimit icon indicating copy to clipboard operation
AspNetCoreRateLimit copied to clipboard

[Question]: ClientId from POST request instead of header

Open RaptorCZ opened this issue 3 years ago • 4 comments

I need to use ClientId provided as parametr in controller's method as POST data. Is there any way?

public async Task<IActionResult> GetData([FromBody] SearchModel model)
{
    var clientId = model.ClientId;
    // use this clientId for throtling
}

RaptorCZ avatar Mar 30 '21 09:03 RaptorCZ

shouldn't this work for you? https://github.com/stefanprodan/AspNetCoreRateLimit/wiki/ClientRateLimitMiddleware#update-rate-limits-at-runtime

manisha201301 avatar Jul 29 '21 15:07 manisha201301

@RaptorCZ Hello, I also want to get the client id from raw data, do you know how to do it?

298029lkk avatar Dec 01 '21 09:12 298029lkk

I had no idea how to do it so I made this "workaround".

I have controller with action:

public async Task<IActionResult> GetAllByRegistrationPlate([FromBody] SearchByRegistrationPlateModel model)
{
}

There is input model SearchByRegistrationPlateModel with CustomerCode

    public class SearchByRegistrationPlateModel
    {
        public string CustomerCode { get; set; }
    }

Then I implemented custom IClientResolveContributor and trying to find CustomerCode in request

    public class CustomResolveContributor : IClientResolveContributor
    {
        private readonly IHttpContextAccessor _httpContextAccessor;

        public CustomResolveContributor(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
        }

        public string ResolveClient()
        {
            if (_httpContextAccessor?.HttpContext == null)
            {
                return string.Empty;
            }

            var request = _httpContextAccessor.HttpContext.Request;

            string clientId;
            try
            {
                request.EnableBuffering();
                var buffer = new byte[Convert.ToInt32(request.ContentLength)];
                request.Body.ReadAsync(buffer, 0, buffer.Length);

                var content = Encoding.UTF8.GetString(buffer);
                clientId = ExtractClientIdFromContent(content);
            }
            catch
            {
                clientId = string.Empty;
            }
            finally
            {
                request.Body.Position = 0;
            }

            return clientId;
        }

        private static string ExtractClientIdFromContent(string content)
        {
            if (string.IsNullOrEmpty(content))
            {
                return string.Empty;
            }

            var options = new JsonSerializerOptions
            {
                PropertyNamingPolicy = JsonNamingPolicy.CamelCase
            };
            var model = JsonSerializer.Deserialize<SearchByRegistrationPlateModel>(content, options);

            var clientId = model?.CustomerCode.ToLower();

            return clientId;
        }
    }

So it is not universal, but it works in my case.

RaptorCZ avatar Dec 01 '21 09:12 RaptorCZ

@RaptorCZ So cool. I think this is the standard method. Thank you very much!

298029lkk avatar Dec 01 '21 09:12 298029lkk