question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

AbstractRateLimitFilter improvements

See original GitHub issue
  1. I suppose it makes sense to extract applyPolicy to the separate class, that would contain a list of other filters, not knowing about concrete implementations. This change will give possibility to add custom policy filters. Something like that:
    private final List<PolicyFilter> filters;
    private final MatchersByTypeIndex matchersIndex;

    @Override
    public boolean filter(HttpServletRequest request, Route route, 
                                       RateLimitProperties.Policy policy) {
        return policy.getType().isEmpty() || allFiltersApply(request, route, policy);
    }

    private boolean allFiltersApply(HttpServletRequest request, Route route, 
                                                        RateLimitProperties.Policy policy) {
        return filters
                .stream()
                .allMatch(policyFilter -> {
                    Set<String> matchers = matchersIndex.get(policyFilter.getType());
                    return policyFilter.filter(matchers, request, route);
                });
    }
  1. Consider using Set instead of List for users and origins in userApply and originApply methods. Complexity of contains operation on set is O(1), on list is O(n). Usage of Set will not degrade app if big amount of matchers is added.
  2. getConfiguredType can be precomputed on startup and instead of list can be saved into map<Type, Set<String>>. So for example instead of:
    private boolean urlApply(List<MatchType> types, Route route) {
        List<String> urls = getConfiguredType(types, Type.URL);

        return urls.isEmpty()
            || route == null
            || urls.stream().anyMatch(url -> route.getPath().startsWith(url));
    }

it can be done this way:

    private boolean urlApply(List<MatchType> types, Route route) {
        Set<String> urls = matchersIndex.getOrDefault(Type.URL, Collections.emptySet());

        return urls.isEmpty()
            || route == null
            || urls.stream().anyMatch(url -> route.getPath().startsWith(url));
    }

This would decrease complexity of the method.

If you are interested I would like to open PRs with described changes.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
Alorencommented, Jun 2, 2018
  1. The main reason behind that change is that AbstractRateLimitFilter knows too much. It does all policies filtering: userApply, originApply, urlApply. I propose to extract these methods to separate simple filters and to use in AbstractRateLimitFilter only compound policy filter. Instead of:
    protected List<Policy> policy(Route route, HttpServletRequest request) {
...
        return policyMap.values().stream()
            .filter(policy -> compoundPolicyFilter.filter(request, route, policy))
            .collect(Collectors.toList());
    }

whereas PolicyFilter would look like this:

@RequiredArgsConstructor
public class OriginPolicyFilter implements PolicyFilter {
    private final RateLimitUtils rateLimitUtils;

    @Override
    public boolean filter(LinkedHashSet<String> originMatchers, HttpServletRequest request, Route route) {
        return originMatchers.isEmpty()
                || originMatchers.contains(rateLimitUtils.getRemoteAddress(request));
    }

    @Override
    public RateLimitProperties.Policy.Type getType() {
        return RateLimitProperties.Policy.Type.ORIGIN;
    }
}

It is just an idea, interfaces can be different. The main point is that adding new filter will not require touching AbstractRateLimitFilter. Moreover changing default logic behind these filtering logic wight now is impossible. 2,3. these points are actually about one thing – having separate configuration index class instead of iterating on configuration each time, so changing current configuration won’t be needed.

is the empty check neccessary? is that about urls.isEmpty()? it is an existing code, i suppose that it is not needed.

0reactions
marcosbarberocommented, Aug 10, 2019

Closing due to inactivity.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Fetching username for type USER through a custom implementation ...
In the method boolean userApply(List types, HttpServletRequest request) in AbstractRateLimitFilter.java. I don't see any way to override this behavior.
Read more >
spring-cloud-zuul-ratelimit from marcosbarbero - Giter VIP
AbstractRateLimitFilter improvements. I suppose it makes sense to extract applyPolicy to the separate class, that would contain a list of other filters, ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found