@RestController @SpringBootApplication public class Application { private static final int B_TO_KIB = 1024; private static final int KIB_TO_MIB = 1024; private final String chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; private final Random r = new Random(); private final Map<Long, Mono<String>> cached = new ConcurrentHashMap<>(); private Mono<String> randomString(long size) { return Mono.just(chars) .map(s -> s.charAt(r.nextInt(chars.length()))) .repeat(size) .reduce(new StringBuilder(), StringBuilder::append) .map(StringBuilder::toString) .cache(); } private <T> Mono<T> delay(Mono<T> element, Long delayMs) { return Mono.justOrEmpty(delayMs).map(Duration::ofMillis).flatMap(Mono::delay).then(element); } private Mono<String> data(long size, Long delay) { return delay(cached.computeIfAbsent(size, this::randomString), delay); } @GetMapping("/1KiB") public Mono<String> get1KiB(@RequestParam(value = "delayMs", required = false) Long delayMs) { return data(B_TO_KIB, delayMs); } @GetMapping("/5KiB") public Mono<String> get5KiB(@RequestParam(value = "delayMs", required = false) Long delayMs) { return data(5 * B_TO_KIB, delayMs); } @GetMapping("/10KiB") public Mono<String> get10KiB(@RequestParam(value = "delayMs", required = false) Long delayMs) { return data(10 * B_TO_KIB, delayMs); } @GetMapping("/100KiB") public Mono<String> get100KiB(@RequestParam(value = "delayMs", required = false) Long delayMs) { return data(100 * B_TO_KIB, delayMs); } @GetMapping("/1MiB") public Mono<String> get1MiB(@RequestParam(value = "delayMs", required = false) Long delayMs) { return data(B_TO_KIB * KIB_TO_MIB, delayMs); } public static void main(String[] args) { SpringApplication.run(Application.class, args); } }