or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

api-management.mdblock-handling.mdcore-integration.mdindex.mdrequest-processing.mdroute-matching.md

api-management.mddocs/

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