0
# API Definition Management
1
2
System for managing custom API definitions that extend beyond simple route-based resource identification, enabling fine-grained control over resource matching and traffic governance.
3
4
## Capabilities
5
6
### GatewayApiMatcherManager
7
8
Static manager for API definition matchers, providing access to registered API definitions and their corresponding matchers.
9
10
```java { .api }
11
/**
12
* Manager for API definition matchers
13
* Provides static access to API matcher registry
14
*/
15
public final class GatewayApiMatcherManager {
16
/**
17
* Gets unmodifiable map of all API matchers
18
* @return Map<String, WebExchangeApiMatcher> - API name to matcher mapping
19
*/
20
public static Map<String, WebExchangeApiMatcher> getApiMatcherMap();
21
22
/**
23
* Gets specific API matcher by name
24
* @param apiName - Name of API definition to retrieve
25
* @return Optional<WebExchangeApiMatcher> - Matcher if found, empty otherwise
26
*/
27
public static Optional<WebExchangeApiMatcher> getMatcher(String apiName);
28
29
/**
30
* Gets set of all registered API definitions
31
* @return Set<ApiDefinition> - All registered API definitions
32
*/
33
public static Set<ApiDefinition> getApiDefinitionSet();
34
35
/**
36
* Loads and registers API definitions (package-private, used internally)
37
* @param definitions - Set of API definitions to load
38
*/
39
static synchronized void loadApiDefinitions(Set<ApiDefinition> definitions);
40
}
41
```
42
43
### WebExchangeApiMatcher
44
45
API matcher implementation for Spring WebFlux ServerWebExchange, extending abstract matcher functionality for reactive gateway environments.
46
47
```java { .api }
48
/**
49
* API matcher implementation for Spring WebFlux ServerWebExchange
50
* Extends AbstractApiMatcher<ServerWebExchange> for reactive environments
51
*/
52
public class WebExchangeApiMatcher extends AbstractApiMatcher<ServerWebExchange> {
53
/**
54
* Constructor with API definition
55
* @param apiDefinition - API definition to create matcher for
56
*/
57
public WebExchangeApiMatcher(ApiDefinition apiDefinition);
58
59
// Inherited from AbstractApiMatcher:
60
/**
61
* Tests if exchange matches the API definition
62
* @param exchange - Server web exchange to test
63
* @return boolean - true if exchange matches API definition
64
*/
65
public boolean test(ServerWebExchange exchange);
66
67
/**
68
* Gets the API name from the definition
69
* @return String - API name
70
*/
71
public String getApiName();
72
73
/**
74
* Gets the underlying API definition
75
* @return ApiDefinition - The API definition used by this matcher
76
*/
77
public ApiDefinition getApiDefinition();
78
}
79
```
80
81
### SpringCloudGatewayApiDefinitionChangeObserver
82
83
Observer for API definition changes, integrating with the common adapter's change notification system.
84
85
```java { .api }
86
/**
87
* Observer for API definition changes in Spring Cloud Gateway environment
88
* Implements ApiDefinitionChangeObserver for change notifications
89
*/
90
public class SpringCloudGatewayApiDefinitionChangeObserver implements ApiDefinitionChangeObserver {
91
/**
92
* Default constructor
93
*/
94
public SpringCloudGatewayApiDefinitionChangeObserver();
95
96
/**
97
* Handles API definition changes by updating matcher registry
98
* @param apiDefinitions - New set of API definitions
99
*/
100
public void onChange(Set<ApiDefinition> apiDefinitions);
101
}
102
```
103
104
## Usage Patterns
105
106
### API Definition Registration
107
108
```java
109
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition;
110
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPathPredicateItem;
111
import com.alibaba.csp.sentinel.adapter.gateway.common.api.GatewayApiDefinitionManager;
112
113
@Configuration
114
public class ApiDefinitionConfiguration {
115
116
@PostConstruct
117
public void initializeApiDefinitions() {
118
Set<ApiDefinition> definitions = new HashSet<>();
119
120
// User management API
121
ApiDefinition userApi = new ApiDefinition("user-api");
122
userApi.setPredicateItems(new HashSet<ApiPathPredicateItem>() {{
123
// Exact path match
124
add(new ApiPathPredicateItem().setPattern("/api/users")
125
.setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_EXACT));
126
// Prefix match for user operations
127
add(new ApiPathPredicateItem().setPattern("/api/users/**")
128
.setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
129
}});
130
definitions.add(userApi);
131
132
// Admin API with regex matching
133
ApiDefinition adminApi = new ApiDefinition("admin-api");
134
adminApi.setPredicateItems(new HashSet<ApiPathPredicateItem>() {{
135
add(new ApiPathPredicateItem().setPattern("/admin/.*")
136
.setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_REGEX));
137
}});
138
definitions.add(adminApi);
139
140
// Register definitions
141
GatewayApiDefinitionManager.loadApiDefinitions(definitions);
142
}
143
}
144
```
145
146
### Custom API Matcher
147
148
```java
149
public class CustomApiMatcher {
150
151
public static boolean matchesUserApiWithAuth(ServerWebExchange exchange) {
152
Optional<WebExchangeApiMatcher> matcher = GatewayApiMatcherManager.getMatcher("user-api");
153
154
if (matcher.isPresent() && matcher.get().test(exchange)) {
155
// Additional check for authentication
156
String authHeader = exchange.getRequest().getHeaders().getFirst("Authorization");
157
return authHeader != null && authHeader.startsWith("Bearer ");
158
}
159
160
return false;
161
}
162
163
public static Set<String> getAllMatchingApis(ServerWebExchange exchange) {
164
return GatewayApiMatcherManager.getApiMatcherMap().entrySet().stream()
165
.filter(entry -> entry.getValue().test(exchange))
166
.map(Map.Entry::getKey)
167
.collect(Collectors.toSet());
168
}
169
}
170
```
171
172
### Dynamic API Definition Updates
173
174
```java
175
@Service
176
public class DynamicApiDefinitionService {
177
178
private final SpringCloudGatewayApiDefinitionChangeObserver observer =
179
new SpringCloudGatewayApiDefinitionChangeObserver();
180
181
public void updateApiDefinitions(Set<ApiDefinition> newDefinitions) {
182
// Validate definitions
183
validateApiDefinitions(newDefinitions);
184
185
// Update through observer (this updates the matcher registry)
186
observer.onChange(newDefinitions);
187
188
// Also update the common manager
189
GatewayApiDefinitionManager.loadApiDefinitions(newDefinitions);
190
}
191
192
private void validateApiDefinitions(Set<ApiDefinition> definitions) {
193
for (ApiDefinition definition : definitions) {
194
if (StringUtil.isBlank(definition.getApiName())) {
195
throw new IllegalArgumentException("API name cannot be blank");
196
}
197
if (definition.getPredicateItems() == null || definition.getPredicateItems().isEmpty()) {
198
throw new IllegalArgumentException("API definition must have predicate items");
199
}
200
}
201
}
202
}
203
```
204
205
### Monitoring API Matches
206
207
```java
208
@Component
209
public class ApiMatchingMonitor {
210
211
public void logApiMatches(ServerWebExchange exchange) {
212
String path = exchange.getRequest().getPath().value();
213
214
Map<String, WebExchangeApiMatcher> matchers = GatewayApiMatcherManager.getApiMatcherMap();
215
216
List<String> matchingApis = matchers.entrySet().stream()
217
.filter(entry -> entry.getValue().test(exchange))
218
.map(Map.Entry::getKey)
219
.collect(Collectors.toList());
220
221
if (!matchingApis.isEmpty()) {
222
log.info("Path {} matched APIs: {}", path, String.join(", ", matchingApis));
223
} else {
224
log.debug("Path {} matched no custom APIs", path);
225
}
226
}
227
228
public Map<String, Integer> getApiMatchStatistics() {
229
// Return statistics about API matching frequency
230
return GatewayApiMatcherManager.getApiDefinitionSet().stream()
231
.collect(Collectors.toMap(
232
ApiDefinition::getApiName,
233
def -> getMatchCountForApi(def.getApiName())
234
));
235
}
236
237
private int getMatchCountForApi(String apiName) {
238
// Implementation would track match counts
239
return 0; // Placeholder
240
}
241
}
242
```
243
244
## API Definition Patterns
245
246
### Path-Based API Definitions
247
248
```java
249
// Exact path matching
250
ApiPathPredicateItem exactPath = new ApiPathPredicateItem()
251
.setPattern("/api/health")
252
.setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_EXACT);
253
254
// Prefix matching (Ant-style)
255
ApiPathPredicateItem prefixPath = new ApiPathPredicateItem()
256
.setPattern("/api/users/**")
257
.setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX);
258
259
// Regex matching
260
ApiPathPredicateItem regexPath = new ApiPathPredicateItem()
261
.setPattern("/api/v[0-9]+/.*")
262
.setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_REGEX);
263
```
264
265
### Composite API Definitions
266
267
```java
268
public ApiDefinition createCompositeApiDefinition() {
269
ApiDefinition apiDef = new ApiDefinition("composite-api");
270
271
Set<ApiPathPredicateItem> predicates = new HashSet<>();
272
273
// Multiple path patterns for the same API
274
predicates.add(new ApiPathPredicateItem()
275
.setPattern("/api/orders/**")
276
.setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
277
278
predicates.add(new ApiPathPredicateItem()
279
.setPattern("/api/payments/**")
280
.setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
281
282
predicates.add(new ApiPathPredicateItem()
283
.setPattern("/api/checkout")
284
.setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_EXACT));
285
286
apiDef.setPredicateItems(predicates);
287
return apiDef;
288
}
289
```
290
291
## Integration with Flow Control
292
293
### API-Based Flow Rules
294
295
```java
296
@Configuration
297
public class ApiFlowRuleConfiguration {
298
299
@PostConstruct
300
public void configureApiFlowRules() {
301
List<FlowRule> rules = new ArrayList<>();
302
303
// Rule for user-api
304
FlowRule userApiRule = new FlowRule();
305
userApiRule.setResource("user-api");
306
userApiRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
307
userApiRule.setCount(100); // 100 QPS limit
308
rules.add(userApiRule);
309
310
// Rule for admin-api with stricter limits
311
FlowRule adminApiRule = new FlowRule();
312
adminApiRule.setResource("admin-api");
313
adminApiRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
314
adminApiRule.setCount(10); // 10 QPS limit
315
rules.add(adminApiRule);
316
317
FlowRuleManager.loadRules(rules);
318
}
319
}
320
```
321
322
## Error Handling
323
324
### Matcher Validation
325
- API definitions are validated when loaded
326
- Invalid patterns or empty API names are rejected
327
- Matcher creation failures are logged and skipped
328
329
### Runtime Safety
330
- All matcher operations are null-safe
331
- Missing matchers return empty Optional or empty collections
332
- Exchange testing handles malformed requests gracefully