All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bardframework.commons.waf.RequestLimitChecker Maven / Gradle / Ivy

The newest version!
package org.bardframework.commons.waf;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.bardframework.commons.waf.exception.CallLimitExceedException;
import org.bardframework.commons.waf.extractor.RequestKeyDetector;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Getter
@Setter
@Slf4j
public class RequestLimitChecker {

    private static final String PREFIX = "CALL_LIMITER_";

    private AntPathRequestMatcher requestMatcher;
    private HttpMethod httpMethod;
    private int limit;
    private int period;
    private TimeUnit periodUnit;
    private Set whiteList = new HashSet<>();
    @Autowired
    private RequestCallCounter requestCallCounter;
    @Autowired
    private RequestKeyDetector requestKeyDetector;

    public RequestLimitChecker() {
    }

    public RequestLimitChecker(String url, RequestCallCounter requestCallCounter, RequestKeyDetector requestKeyDetector, int limit, int period, TimeUnit periodUnit) {
        this.httpMethod = null;
        this.requestMatcher = new AntPathRequestMatcher(url);
        this.requestCallCounter = requestCallCounter;
        this.requestKeyDetector = requestKeyDetector;
        this.limit = limit;
        this.period = period;
        this.periodUnit = periodUnit;
    }

    public RequestLimitChecker(HttpMethod httpMethod, String url, RequestCallCounter requestCallCounter, RequestKeyDetector requestKeyDetector, int limit, int period, TimeUnit periodUnit) {
        this.httpMethod = httpMethod;
        this.requestMatcher = new AntPathRequestMatcher(url, httpMethod.name());
        this.requestCallCounter = requestCallCounter;
        this.requestKeyDetector = requestKeyDetector;
        this.limit = limit;
        this.period = period;
        this.periodUnit = periodUnit;
    }

    public void checkCallLimit(HttpServletRequest request, HttpServletResponse response) throws CallLimitExceedException {
        String key = this.getRequestKeyDetector().getUniqueKey(request, response);
        if (null == key) {
            log.warn("can't detect unique key of request [{} {}] for checking call limit", request.getMethod(), request.getRequestURI());
            return;
        }
        if (this.getWhiteList().contains(key)) {
            log.debug("request [{} {}] with unique key[{}] not checked, unique key is in white list", request.getMethod(), request.getRequestURI(), key);
            return;
        }
        key = PREFIX + key + (null == this.getHttpMethod() ? "" : "@" + this.getHttpMethod()) + "@" + this.getRequestMatcher().getPattern();
        long count = this.getRequestCallCounter().increment(key);
        if (count > this.getLimit()) {
            throw new CallLimitExceedException(key);
        }
        if (count == 1) {
            this.getRequestCallCounter().expire(key, this.getPeriod(), this.getPeriodUnit());
        }
    }

    public boolean match(HttpServletRequest request) {
        return this.getRequestMatcher().matches(request);
    }

    public void setWhiteList(String... whiteList) {
        this.whiteList = new HashSet<>(List.of(whiteList));
    }

    public void setUrl(String url) {
        this.requestMatcher = new AntPathRequestMatcher(url);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy