class LimitHandler implements MiddlewareHandler {
    static final Logger logger = LoggerFactory.getLogger(LimitHandler.class);

    private volatile HttpHandler next;
    private static RateLimiter rateLimiter;
    private final LimitConfig config;
    private static final ObjectMapper mapper = Config.getInstance().getMapper();


    public LimitHandler() throws Exception{
        config = LimitConfig.load();
        logger.info("RateLimit started with key type:" + config.getKey().name());
        rateLimiter = new RateLimiter(config);
    }

    /**
     * This is a constructor for test cases only. Please don't use it.
     *
     * @param cfg limit config
     * @throws Exception thrown when config is wrong.
     *
     */
    @Deprecated
    public LimitHandler(LimitConfig cfg) throws Exception{
        config = cfg;
        logger.info("RateLimit started with key type:" + config.getKey().name());
        rateLimiter = new RateLimiter(cfg);
    }

    @Override
    public void handleRequest(final HttpServerExchange exchange) throws Exception {
        if(logger.isDebugEnabled()) logger.debug("LimitHandler.handleRequest starts.");
        RateLimitResponse rateLimitResponse = rateLimiter.handleRequest(exchange, config.getKey());
        if (rateLimitResponse.allow) {
            if(logger.isDebugEnabled()) logger.debug("LimitHandler.handleRequest ends.");
            Handler.next(exchange, next);
        } else {
            exchange.getResponseHeaders().add(new HttpString(Constants.RATELIMIT_LIMIT), rateLimitResponse.getHeaders().get(Constants.RATELIMIT_LIMIT));
            exchange.getResponseHeaders().add(new HttpString(Constants.RATELIMIT_REMAINING), rateLimitResponse.getHeaders().get(Constants.RATELIMIT_REMAINING));
            exchange.getResponseHeaders().add(new HttpString(Constants.RATELIMIT_RESET), rateLimitResponse.getHeaders().get(Constants.RATELIMIT_RESET));

            exchange.getResponseHeaders().add(new HttpString("Content-Type"), "application/json");
            int statusCode = config.getErrorCode()==0 ? HttpStatus.TOO_MANY_REQUESTS.value():config.getErrorCode();
            exchange.setStatusCode(statusCode);
            if(logger.isDebugEnabled()) logger.warn("LimitHandler.handleRequest ends with an error code {}", statusCode);
            exchange.getResponseSender().send(mapper.writeValueAsString(rateLimitResponse));
        }
    }

    @Override
    public HttpHandler getNext() {
        return next;
    }

    @Override
    public MiddlewareHandler setNext(final HttpHandler next) {
        Handlers.handlerNotNull(next);
        this.next = next;
        return this;
    }

    @Override
    public boolean isEnabled() {
        return config.isEnabled();
    }

    @Override
    public void register() {
        ModuleRegistry.registerModule(LimitConfig.CONFIG_NAME, LimitHandler.class.getName(), Config.getNoneDecryptedInstance().getJsonMapConfigNoCache(LimitConfig.CONFIG_NAME), null);
    }

    @Override
    public void reload() {<FILL_FUNCTION_BODY>}
}

        config.reload();
        try {
            rateLimiter = new RateLimiter(config);
        } catch (Exception e) {
            logger.error("Failed to recreate RateLimiter with reloaded config.", e);
        }
        // after reload, we need to update the config in the module registry to ensure that server info returns the latest configuration.
        ModuleRegistry.registerModule(LimitConfig.CONFIG_NAME, LimitHandler.class.getName(), Config.getNoneDecryptedInstance().getJsonMapConfigNoCache(LimitConfig.CONFIG_NAME), null);
        if(logger.isInfoEnabled()) logger.info("LimitHandler is reloaded.");
    
<no_super_class>