Cors issue when returning error in filter

When we are having some back to back API calls, on the Web Client side we are hitting CORS issues.

We found that the Request Headers are set correctly but still CORS are hit. We found that internally the APIs error out with Error Code 429 – Too many requests. See image attached. This response header should be set correctly to inform Web Client that the error is 429 and not CORS.

The filter we have is a throttling filter and the Cors issue happens when it return the 429 error

      public ThrottlingAttribute(double threshold)
    {           
        Threshold = TimeSpan.FromSeconds(threshold);                
    }
    public override void Execute(IRequest req, IResponse res, object requestDto)
    {
        var now = DateTime.Now;         
        var reqIdentity = String.Format("{0}:{1}", requestDto.GetType().Name, req.Headers["x-api-key"]);
        
        if(ExludedApiKeys.Contains(req.Headers["x-api-key"].ToUpper()) || ExludedTestApiKeys.Contains(req.Headers["x-api-key"].ToUpper()))
            return;

        if (RequestLog.TryAdd(reqIdentity, now))
        {
            return;
        }
        
        DateTime lastCall;
        if (!RequestLog.TryGetValue(reqIdentity, out lastCall))
        {
            return;
        }

        if (lastCall + Threshold >= now)
        {
            res.StatusCode = 429;
            res.StatusDescription = "Too many Requests. Back-off and try again later.";
            res.Close();
            return;
        }

        RequestLog.TryUpdate(reqIdentity, now, lastCall);
    }

bild

How can we return the error message correctly from the filter without getting the CORS issues. Other request returning an error inside the services dont get the Cors issues

Hi @bokamera,

CORS support needs to add some additional headers in the response as you know but your rate limiting filter is closing the response likely before the GlobalResponseHeaders for the CorsFeature plugin can write the response headers required. You might find errors in your logs regarding Failed Adding Headers.

You’ll want to instead throw a HttpError rather than manipulate the response directly unless there was another reason for doing it this way? Eg

throw new HttpError(429, "Too Many Requests", "You have exceeded your rate limit, it will be reset");

To test this out for yourself, you can use the following request filter attribute to see the difference between the response headers.

public class ThrottleAttribute : RequestFilterAttribute
{
    private static int count = 0;
    public override void Execute(IRequest req, IResponse res, object requestDto)
    {
        count++;
        if (count % 2 == 0)
        {
            throw new HttpError(429, "Too Many Requests", "You have exceeded your rate limit, it will be reset");
        }
        else
        {
            res.Close();
        }
    }
}

Putting this on a service you’ll see one response has the expected access-control-allow-origin related headers and the res.Close(); response doesn’t. Eg,

[Throttle]
public class MyServices : Service
{
    public object Any(Hello request)
    {
        return new HelloResponse { Result = $"Hello, {request.Name}!" };
    }
}

Hope that helps!

Don’t immediately terminate the connection use EndRequest() so global response headers are added and request finalizers are run.

res.EndRequest();
1 Like

Thx for your very good explination and exampl. I did try with setting EndRequest instead of Closing it and that solved the problem.

2 Likes