Add comprehensive Javadoc documentation to server components, including annotations, request/response handling, routing, and WebSocket support.
This commit is contained in:
@@ -5,11 +5,35 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Immutable mapping from request paths to the {@link Rule rate-limit rules} that apply to them.
|
||||
*
|
||||
* <p>Three kinds of rules can be configured, resolved with the following precedence by
|
||||
* {@link #rulesFor(String)}:</p>
|
||||
* <ol>
|
||||
* <li>an optional <strong>global</strong> rule that applies to every request;</li>
|
||||
* <li><strong>exact-path</strong> rules matched by exact path equality;</li>
|
||||
* <li><strong>prefix</strong> rules matched by path prefix, evaluated longest-prefix-first.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>A request is subject to the global rule (if any) plus the single most specific path rule
|
||||
* that matches. Instances are built through the nested {@link Builder}.</p>
|
||||
*/
|
||||
public final class RateLimitConfig {
|
||||
|
||||
/** Rule applied to every request, or {@code null} if no global rule is configured. */
|
||||
private final Rule globalRule;
|
||||
/** Rules matched by exact path equality, keyed by path. */
|
||||
private final Map<String, Rule> exactPathRules;
|
||||
/** Prefix rules, pre-sorted longest-prefix-first so the most specific match wins. */
|
||||
private final List<PrefixRule> prefixRules;
|
||||
|
||||
/**
|
||||
* Builds an immutable configuration from a {@link Builder}, copying the exact-path rules
|
||||
* and sorting the prefix rules by descending prefix length.
|
||||
*
|
||||
* @param b the builder carrying the configured rules
|
||||
*/
|
||||
private RateLimitConfig(Builder b) {
|
||||
this.globalRule = b.globalRule;
|
||||
this.exactPathRules = Map.copyOf(b.exactPathRules);
|
||||
@@ -18,10 +42,25 @@ public final class RateLimitConfig {
|
||||
.toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new, empty {@link Builder}.
|
||||
*
|
||||
* @return a fresh builder
|
||||
*/
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ordered list of rules that apply to the given path.
|
||||
*
|
||||
* <p>The list contains the global rule first (if configured) followed by at most one
|
||||
* path-specific rule: the exact-path rule if one matches, otherwise the longest matching
|
||||
* prefix rule. The returned list may be empty if no rule applies.</p>
|
||||
*
|
||||
* @param path the request path
|
||||
* @return the applicable rules, in evaluation order
|
||||
*/
|
||||
public List<Rule> rulesFor(String path) {
|
||||
List<Rule> rules = new ArrayList<>(2);
|
||||
if (globalRule != null) rules.add(globalRule);
|
||||
@@ -40,34 +79,83 @@ public final class RateLimitConfig {
|
||||
return rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* A single rate-limit rule: a limiter, the key resolver feeding it, and a name used to
|
||||
* namespace keys and aid diagnostics.
|
||||
*
|
||||
* @param limiter the limiter that enforces the quota
|
||||
* @param keyResolver resolves the per-request key the limiter buckets on
|
||||
* @param name a human-readable label (e.g. {@code "global"} or a path/prefix)
|
||||
*/
|
||||
public record Rule(RateLimiter limiter, KeyResolver keyResolver, String name) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal pairing of a path prefix with the rule that applies to paths starting with it.
|
||||
*
|
||||
* @param prefix the path prefix
|
||||
* @param rule the rule to apply for matching paths
|
||||
*/
|
||||
private record PrefixRule(String prefix, Rule rule) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Fluent builder for {@link RateLimitConfig}.
|
||||
*/
|
||||
public static final class Builder {
|
||||
/** Accumulated exact-path rules, keyed by path. */
|
||||
private final Map<String, Rule> exactPathRules = new HashMap<>();
|
||||
/** Accumulated prefix rules. */
|
||||
private final List<PrefixRule> prefixRules = new ArrayList<>();
|
||||
/** The global rule, if configured. */
|
||||
private Rule globalRule;
|
||||
|
||||
/**
|
||||
* Sets the global rule applied to every request.
|
||||
*
|
||||
* @param limiter the limiter enforcing the global quota
|
||||
* @param keys the key resolver for the global rule
|
||||
* @return this builder, for fluent chaining
|
||||
*/
|
||||
public Builder global(RateLimiter limiter, KeyResolver keys) {
|
||||
this.globalRule = new Rule(limiter, keys, "global");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a rule that applies only to requests whose path equals {@code path} exactly.
|
||||
*
|
||||
* @param path the exact request path
|
||||
* @param limiter the limiter enforcing the quota
|
||||
* @param keys the key resolver for this rule
|
||||
* @return this builder, for fluent chaining
|
||||
*/
|
||||
public Builder forPath(String path, RateLimiter limiter, KeyResolver keys) {
|
||||
exactPathRules.put(path, new Rule(limiter, keys, path));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a rule that applies to requests whose path starts with {@code prefix}. When
|
||||
* several prefixes match, the longest one wins.
|
||||
*
|
||||
* @param prefix the path prefix
|
||||
* @param limiter the limiter enforcing the quota
|
||||
* @param keys the key resolver for this rule
|
||||
* @return this builder, for fluent chaining
|
||||
*/
|
||||
public Builder forPrefix(String prefix, RateLimiter limiter, KeyResolver keys) {
|
||||
prefixRules.add(new PrefixRule(prefix, new Rule(limiter, keys, prefix + "*")));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the immutable {@link RateLimitConfig}.
|
||||
*
|
||||
* @return the configured instance
|
||||
*/
|
||||
public RateLimitConfig build() {
|
||||
return new RateLimitConfig(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user