or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdconnection-management.mdcontext-resources.mdhandlers.mdindex.mdrequest-logging.mdrequest-response.mdsecurity-ssl.mdserver-core.mdsession-management.mdutility-handlers.md

handlers.mddocs/

0

# Handler System

1

2

The Handler system provides a flexible framework for processing HTTP requests using a chain-of-responsibility pattern. Handlers can wrap, delegate, and transform requests and responses.

3

4

## Handler Interface

5

6

The core `Handler` interface extends request handling with lifecycle and server management.

7

8

```java { .api }

9

public interface Handler extends LifeCycle, Destroyable, Request.Handler {

10

// Server association

11

Server getServer();

12

void setServer(Server server);

13

14

// Request handling (from Request.Handler)

15

boolean handle(Request request, Response response, Callback callback) throws Exception;

16

17

// Nested interfaces for organization

18

interface Container extends Handler {

19

List<Handler> getHandlers();

20

boolean insertHandler(Handler handler);

21

boolean removeHandler(Handler handler);

22

}

23

24

interface Collection extends Handler.Container {

25

// Collection-specific operations

26

}

27

28

interface Singleton extends Handler.Container {

29

Handler getHandler();

30

void setHandler(Handler handler);

31

}

32

}

33

```

34

35

## Base Handler Classes

36

37

### Handler.Abstract

38

39

Abstract base implementation providing common handler functionality.

40

41

```java { .api }

42

public abstract class Handler.Abstract extends AbstractLifeCycle implements Handler {

43

// Server management

44

public Server getServer();

45

public void setServer(Server server);

46

47

// Template method for request handling

48

public abstract boolean handle(Request request, Response response, Callback callback)

49

throws Exception;

50

51

// Utility methods

52

protected boolean isStarted();

53

protected void doStart() throws Exception;

54

protected void doStop() throws Exception;

55

}

56

```

57

58

### Handler.Wrapper

59

60

Wrapper implementation that delegates to a single child handler.

61

62

```java { .api }

63

public class Handler.Wrapper extends Handler.AbstractContainer implements Handler.Singleton {

64

// Child handler management

65

public Handler getHandler();

66

public void setHandler(Handler handler);

67

68

// Default delegation to child handler

69

public boolean handle(Request request, Response response, Callback callback) throws Exception {

70

Handler handler = getHandler();

71

return handler != null && handler.handle(request, response, callback);

72

}

73

}

74

```

75

76

### Handler.Sequence

77

78

Sequential handler implementation that processes handlers in order.

79

80

```java { .api }

81

public class Handler.Sequence extends Handler.AbstractContainer implements Handler.Collection {

82

// Handler collection management

83

public List<Handler> getHandlers();

84

public boolean insertHandler(Handler handler);

85

public boolean removeHandler(Handler handler);

86

public void setHandlers(List<Handler> handlers);

87

88

// Sequential processing

89

public boolean handle(Request request, Response response, Callback callback) throws Exception;

90

}

91

```

92

93

## Usage Examples

94

95

### Simple Handler Implementation

96

97

```java

98

public class HelloWorldHandler extends Handler.Abstract {

99

@Override

100

public boolean handle(Request request, Response response, Callback callback)

101

throws Exception {

102

103

// Set response headers

104

response.setStatus(200);

105

response.getHeaders().put("Content-Type", "text/plain");

106

107

// Write response body

108

String message = "Hello, World! Time: " + Instant.now();

109

response.write(true, ByteBuffer.wrap(message.getBytes()), callback);

110

111

return true; // Request handled

112

}

113

}

114

```

115

116

### Path-Based Routing Handler

117

118

```java

119

public class RoutingHandler extends Handler.Abstract {

120

private final Map<String, Handler> routes = new HashMap<>();

121

122

public void addRoute(String path, Handler handler) {

123

routes.put(path, handler);

124

addBean(handler); // Manage lifecycle

125

}

126

127

@Override

128

public boolean handle(Request request, Response response, Callback callback)

129

throws Exception {

130

131

String path = request.getHttpURI().getPath();

132

Handler handler = routes.get(path);

133

134

if (handler != null) {

135

return handler.handle(request, response, callback);

136

}

137

138

// No route found

139

return false;

140

}

141

}

142

143

// Usage

144

RoutingHandler router = new RoutingHandler();

145

router.addRoute("/hello", new HelloWorldHandler());

146

router.addRoute("/api/status", new StatusHandler());

147

router.addRoute("/api/users", new UsersHandler());

148

149

server.setHandler(router);

150

```

151

152

### Wrapper Handler with Request/Response Modification

153

154

```java

155

public class TimingHandler extends Handler.Wrapper {

156

157

@Override

158

public boolean handle(Request request, Response response, Callback callback)

159

throws Exception {

160

161

long startTime = System.nanoTime();

162

163

// Wrap callback to measure timing

164

Callback timingCallback = new Callback() {

165

@Override

166

public void succeeded() {

167

long duration = System.nanoTime() - startTime;

168

response.getHeaders().add("X-Processing-Time-Nanos", String.valueOf(duration));

169

callback.succeeded();

170

}

171

172

@Override

173

public void failed(Throwable x) {

174

long duration = System.nanoTime() - startTime;

175

System.err.println("Request failed after " + duration + " nanos: " + x.getMessage());

176

callback.failed(x);

177

}

178

};

179

180

// Delegate to child handler with timing callback

181

return super.handle(request, response, timingCallback);

182

}

183

}

184

```

185

186

### Sequential Handler Processing

187

188

```java

189

public class FilteredHandler extends Handler.Sequence {

190

191

public FilteredHandler() {

192

// Add handlers in order of execution

193

addHandler(new AuthenticationHandler());

194

addHandler(new LoggingHandler());

195

addHandler(new CompressionHandler());

196

addHandler(new ApplicationHandler());

197

}

198

}

199

200

// Authentication filter

201

public class AuthenticationHandler extends Handler.Abstract {

202

@Override

203

public boolean handle(Request request, Response response, Callback callback)

204

throws Exception {

205

206

String authHeader = request.getHeaders().get("Authorization");

207

if (authHeader == null || !isValidAuth(authHeader)) {

208

response.setStatus(401);

209

response.getHeaders().put("Content-Type", "text/plain");

210

response.write(true, ByteBuffer.wrap("Unauthorized".getBytes()), callback);

211

return true; // Request handled (rejected)

212

}

213

214

return false; // Continue to next handler

215

}

216

217

private boolean isValidAuth(String authHeader) {

218

// Validate authentication token

219

return authHeader.startsWith("Bearer ") && authHeader.length() > 20;

220

}

221

}

222

```

223

224

## Advanced Handler Patterns

225

226

### Conditional Handler Processing

227

228

```java

229

public abstract class ConditionalHandler extends Handler.Wrapper {

230

231

@Override

232

public boolean handle(Request request, Response response, Callback callback)

233

throws Exception {

234

235

if (shouldHandle(request)) {

236

return handleConditionally(request, response, callback);

237

} else {

238

return super.handle(request, response, callback);

239

}

240

}

241

242

protected abstract boolean shouldHandle(Request request);

243

244

protected boolean handleConditionally(Request request, Response response, Callback callback)

245

throws Exception {

246

// Default: delegate to child

247

return super.handle(request, response, callback);

248

}

249

}

250

251

// IP-based access control

252

public class IPRestrictedHandler extends ConditionalHandler {

253

private final Set<String> allowedIPs;

254

255

public IPRestrictedHandler(Set<String> allowedIPs) {

256

this.allowedIPs = allowedIPs;

257

}

258

259

@Override

260

protected boolean shouldHandle(Request request) {

261

String clientIP = request.getConnectionMetaData()

262

.getRemoteSocketAddress().toString();

263

return !allowedIPs.contains(clientIP);

264

}

265

266

@Override

267

protected boolean handleConditionally(Request request, Response response, Callback callback)

268

throws Exception {

269

// Reject forbidden IPs

270

response.setStatus(403);

271

response.getHeaders().put("Content-Type", "text/plain");

272

response.write(true, ByteBuffer.wrap("Access Denied".getBytes()), callback);

273

return true;

274

}

275

}

276

```

277

278

### Asynchronous Handler Processing

279

280

```java

281

public class AsyncProcessingHandler extends Handler.Abstract {

282

private final ExecutorService executor = Executors.newCachedThreadPool();

283

284

@Override

285

public boolean handle(Request request, Response response, Callback callback)

286

throws Exception {

287

288

// Process request asynchronously

289

CompletableFuture.supplyAsync(() -> {

290

try {

291

// Simulate async processing

292

Thread.sleep(1000);

293

return processRequest(request);

294

} catch (Exception e) {

295

throw new RuntimeException(e);

296

}

297

}, executor).thenAccept(result -> {

298

// Generate response

299

response.setStatus(200);

300

response.getHeaders().put("Content-Type", "application/json");

301

302

String json = "{\"result\": \"" + result + "\", \"async\": true}";

303

response.write(true, ByteBuffer.wrap(json.getBytes()), callback);

304

305

}).exceptionally(throwable -> {

306

// Handle error

307

response.setStatus(500);

308

response.getHeaders().put("Content-Type", "text/plain");

309

response.write(true, ByteBuffer.wrap("Processing failed".getBytes()), callback);

310

return null;

311

});

312

313

return true; // Request handling started

314

}

315

316

private String processRequest(Request request) {

317

// Simulate complex processing

318

return "Processed: " + request.getHttpURI().getPath();

319

}

320

321

@Override

322

protected void doStop() throws Exception {

323

executor.shutdown();

324

super.doStop();

325

}

326

}

327

```

328

329

## Handler Collections and Containers

330

331

### Handler.Collection Interface

332

333

```java { .api }

334

public interface Handler.Collection extends Handler.Container {

335

// Inherited from Container:

336

List<Handler> getHandlers();

337

boolean insertHandler(Handler handler);

338

boolean removeHandler(Handler handler);

339

340

// Collection-specific operations

341

void setHandlers(List<Handler> handlers);

342

void addHandler(Handler handler);

343

}

344

```

345

346

### Handler.Container Interface

347

348

```java { .api }

349

public interface Handler.Container extends Handler {

350

List<Handler> getHandlers();

351

boolean insertHandler(Handler handler);

352

boolean removeHandler(Handler handler);

353

354

// Descendants and lifecycle management

355

Handler getDescendant(Class<? extends Handler> type);

356

<T extends Handler> List<T> getDescendants(Class<T> type);

357

}

358

```

359

360

## Handler Utilities

361

362

### Handler Tree Navigation

363

364

```java

365

public class HandlerTreeExample {

366

public void exploreHandlerTree(Handler root) {

367

if (root instanceof Handler.Container) {

368

Handler.Container container = (Handler.Container) root;

369

370

// Get all child handlers

371

List<Handler> children = container.getHandlers();

372

373

// Find specific handler type

374

Handler errorHandler = container.getDescendant(ErrorHandler.class);

375

376

// Find all handlers of specific type

377

List<StatisticsHandler> statsHandlers =

378

container.getDescendants(StatisticsHandler.class);

379

380

// Process each child

381

for (Handler child : children) {

382

System.out.println("Handler: " + child.getClass().getSimpleName());

383

exploreHandlerTree(child); // Recursive traversal

384

}

385

}

386

}

387

}

388

```

389

390

### Dynamic Handler Management

391

392

```java

393

public class DynamicHandlerManager {

394

private final Handler.Sequence mainHandler;

395

396

public DynamicHandlerManager() {

397

this.mainHandler = new Handler.Sequence();

398

}

399

400

public void addMiddleware(Handler middleware) {

401

// Insert before the last handler (usually the application handler)

402

List<Handler> handlers = new ArrayList<>(mainHandler.getHandlers());

403

if (handlers.size() > 0) {

404

handlers.add(handlers.size() - 1, middleware);

405

} else {

406

handlers.add(middleware);

407

}

408

mainHandler.setHandlers(handlers);

409

}

410

411

public void removeMiddleware(Class<? extends Handler> middlewareType) {

412

List<Handler> handlers = new ArrayList<>(mainHandler.getHandlers());

413

handlers.removeIf(h -> middlewareType.isInstance(h));

414

mainHandler.setHandlers(handlers);

415

}

416

417

public Handler getRootHandler() {

418

return mainHandler;

419

}

420

}

421

422

// Usage

423

DynamicHandlerManager manager = new DynamicHandlerManager();

424

manager.addMiddleware(new LoggingHandler());

425

manager.addMiddleware(new AuthenticationHandler());

426

manager.addMiddleware(new ApplicationHandler());

427

428

server.setHandler(manager.getRootHandler());

429

```

430

431

## Handler Lifecycle

432

433

All handlers participate in the server lifecycle:

434

435

```java

436

public class LifecycleAwareHandler extends Handler.Abstract {

437

438

@Override

439

protected void doStart() throws Exception {

440

super.doStart();

441

System.out.println("Handler starting: " + this.getClass().getSimpleName());

442

443

// Initialize resources

444

initializeDatabase();

445

startBackgroundTasks();

446

}

447

448

@Override

449

protected void doStop() throws Exception {

450

System.out.println("Handler stopping: " + this.getClass().getSimpleName());

451

452

// Cleanup resources

453

stopBackgroundTasks();

454

closeDatabase();

455

456

super.doStop();

457

}

458

459

private void initializeDatabase() {

460

// Setup database connections

461

}

462

463

private void startBackgroundTasks() {

464

// Start scheduled tasks

465

}

466

467

private void stopBackgroundTasks() {

468

// Stop scheduled tasks

469

}

470

471

private void closeDatabase() {

472

// Close database connections

473

}

474

}

475

```