Backend Development 6 min read

Implementing Request Rate Limiting in Moco with a Custom LimitHandler

This article explains how to extend the Moco API with a custom LimitHandler to restrict request frequency, provides the Java implementation of the handler, and demonstrates several overloads for configuring default and custom intervals for rate limiting in backend testing scenarios.

FunTester
FunTester
FunTester
Implementing Request Rate Limiting in Moco with a Custom LimitHandler

When using the Moco API, some required testing features are not available out‑of‑the‑box, so a custom solution is needed; this article introduces a LimitHandler that limits the number of accesses regardless of session or user.

The limit functionality is useful for scenarios such as lottery draws in mini‑games, order submissions, or any operation that should not be invoked repeatedly within a short time window.

package com.fun.moco.support; import com.fun.utils.Time; import com.github.dreamhead.moco.HttpRequest; import com.github.dreamhead.moco.MocoConfig; import com.github.dreamhead.moco.ResponseHandler; import com.github.dreamhead.moco.handler.AbstractResponseHandler; import com.github.dreamhead.moco.internal.SessionContext; import com.github.dreamhead.moco.model.MessageContent; import com.google.common.base.Function; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @SuppressWarnings("all") public class LimitHandle extends AbstractResponseHandler { private final ResponseHandler limit; private final ResponseHandler unlimit; private Map tatal = new ConcurrentHashMap<>(); private int interval; private LimitHandle(final ResponseHandler limit, final ResponseHandler unLimit, int interval) { this.limit = limit; this.unlimit = unLimit; this.interval = interval; } public static ResponseHandler newSeq(final ResponseHandler limit, final ResponseHandler unLimit, int interval) { return new LimitHandle(limit, unLimit, interval); } @Override public void writeToResponse(final SessionContext context) { HttpRequest request = (HttpRequest) context.getRequest(); String uri = request.getUri(); MessageContent content = request.getContent(); (limited(uri + content) ? limit : unlimit).writeToResponse(context); } @Override public ResponseHandler apply(final MocoConfig config) { if (config.isFor(MocoConfig.RESPONSE_ID)) { return super.apply(config); } return new LimitHandle(limit, unlimit, interval); } private Function applyConfig(final MocoConfig config) { return new Function () { @Override public ResponseHandler apply(final ResponseHandler input) { return input.apply(config); } }; } /** * Determine whether the request is limited. * By recording the timestamp of each response, the method checks if the interval between two requests exceeds the configured limit. */ public boolean limited(String info) { long fresh = Time.getTimeStamp(); long old = tatal.containsKey(info) ? tatal.get(info) : 0L; tatal.put(info, fresh); return fresh - old > interval; } }

The handler can be used through a set of static limit methods that accept either plain strings, JSON objects, or other ResponseHandler instances, with an optional interval parameter (default 1000 ms):

/** * Limit request frequency, default 1000 ms */ static ResponseHandler limit(String limited, String unlimited) { limit(contentResponse(limited), contentResponse(unlimited)); } static ResponseHandler limit(JSONObject limited, JSONObject unlimited) { limit(jsonResponse(limited), jsonResponse(unlimited)); } static ResponseHandler limit(ResponseHandler limited, ResponseHandler unlimited) { limit(limited, unlimited, 1000); } /** * Limit request frequency with custom interval (ms) */ static ResponseHandler limit(String limited, String unlimited, int interval) { limit(contentResponse(limited), contentResponse(unlimited), interval); } static ResponseHandler limit(JSONObject limited, JSONObject unlimited, int interval) { limit(limited.toString(), unlimited.toString(), interval); } static ResponseHandler limit(ResponseHandler limit, ResponseHandler unlimit, int interval) { return LimitHandle.newSeq(limit, unlimit, interval); }

Additionally, the article includes a brief commentary on Groovy, noting its strong Java compatibility, low learning curve, and excellent IDE support, which can be advantageous when working with JVM‑based testing tools.

Javabackend testingAPIRate LimitingMoco
FunTester
Written by

FunTester

10k followers, 1k articles | completely useless

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.