1

I would like to restrict frequent requests to my Spring Boot controller for example based on an incoming parameter a country, allow only n requests per m seconds from a particular country.

I have some solution however would like to ask whether there is a better (proper, more elegant) approach.

Controller:

@RestController
public class UslugiController {

    @Autowired
    private CheckService checkService;

    @GetMapping("/apply/{country}")
    public ResponseEntity<?> apply(@PathVariable String country){

        if (!checkService.allowRequestByFrequency(country)){
            return ResponseEntity
                    .status(HttpStatus.BAD_REQUEST)
                    .body("{\"message\":\"Too frequent requests\"}");
        }

        return ResponseEntity
                .status(HttpStatus.OK)
                .body("{\"message\":\"OK\"}");

    }

}

Service:

@Service
public class CheckService {

    private Map<String, CircularFifoQueue<LocalTime>> requests = new HashMap<>();

    @Value("${max.time.period.sec}")
    private int maxAllowedPeriodSeconds;

    @Value("${max.number.requests.in.period}")
    public int numberRequestsInPeriod;

    @PostConstruct
    private void post() {
        requests.put("EN", new CircularFifoQueue<LocalTime>(numberRequestsInPeriod));
        requests.put("RU", new CircularFifoQueue<LocalTime>(numberRequestsInPeriod));
    }


    // check if a number of requests for particular country is not more then n per m seconds
    public boolean allowRequestByFrequency(String country) {

        CircularFifoQueue<LocalTime> requestsTimes = requests.get(country);
        requestsTimes.add(LocalTime.now());

        //wait until queue is full
        if (!requestsTimes.isAtFullCapacity()){
            return true;
        }

        LocalTime firstReq = requestsTimes.get(0);
        LocalTime lastReq = requestsTimes.get(requestsTimes.maxSize()-1);
        long periodSeconds = Duration.between(firstReq, lastReq).getSeconds();

        return periodSeconds > maxAllowedPeriodSeconds;

    }

}
Kirill Ch
  • 5,496
  • 4
  • 44
  • 65

0 Answers0