or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdparameter-injection.mdreactive-streaming.mdrequest-context.mdrequest-filtering.mdroute-declaration.md

request-context.mddocs/

0

# Request Context and Exchange

1

2

Comprehensive interface for accessing and manipulating HTTP request and response objects, providing both low-level Vert.x access and high-level convenience methods.

3

4

## Capabilities

5

6

### RoutingExchange Interface

7

8

Primary interface providing convenient access to HTTP request/response context with both low-level Vert.x access and high-level convenience methods.

9

10

```java { .api }

11

/**

12

* Convenient wrapper around Vert.x RoutingContext for route methods

13

* Provides access to request/response objects and convenience methods

14

*/

15

public interface RoutingExchange {

16

17

/**

18

* Access to underlying Vert.x RoutingContext

19

* @return The Vert.x routing context

20

*/

21

io.vertx.ext.web.RoutingContext context();

22

23

/**

24

* Access to HTTP request object

25

* @return Vert.x HTTP server request

26

*/

27

io.vertx.core.http.HttpServerRequest request();

28

29

/**

30

* Access to HTTP response object

31

* @return Vert.x HTTP server response

32

*/

33

io.vertx.core.http.HttpServerResponse response();

34

35

/**

36

* Get request parameter by name

37

* @param name Parameter name

38

* @return Optional parameter value

39

*/

40

Optional<String> getParam(String name);

41

42

/**

43

* Get HTTP header by name

44

* @param name Header name (accepts CharSequence for flexibility)

45

* @return Optional header value

46

*/

47

Optional<String> getHeader(CharSequence name);

48

49

/**

50

* Set response status to 200 and return response object for chaining

51

* Must call HttpServerResponse.end() to complete the response

52

* @return The HTTP response object for chaining

53

*/

54

io.vertx.core.http.HttpServerResponse ok();

55

56

/**

57

* Set response status to 200, write content, and end response

58

* @param chunk Response content to write

59

*/

60

void ok(String chunk);

61

62

/**

63

* Set response status to 500 and return response object for chaining

64

* Must call HttpServerResponse.end() to complete the response

65

* @return The HTTP response object for chaining

66

*/

67

io.vertx.core.http.HttpServerResponse serverError();

68

69

/**

70

* Set response status to 404 and return response object for chaining

71

* Must call HttpServerResponse.end() to complete the response

72

* @return The HTTP response object for chaining

73

*/

74

io.vertx.core.http.HttpServerResponse notFound();

75

}

76

```

77

78

**Usage Examples:**

79

80

```java

81

import io.quarkus.vertx.web.RoutingExchange;

82

import io.vertx.core.http.HttpHeaders;

83

84

@ApplicationScoped

85

public class ContextExamples {

86

87

// Basic context access

88

@Route(path = "/info", methods = HttpMethod.GET)

89

public String getRequestInfo(RoutingExchange exchange) {

90

String method = exchange.request().method().name();

91

String path = exchange.request().path();

92

String userAgent = exchange.getHeader("User-Agent").orElse("Unknown");

93

94

return String.format("Method: %s, Path: %s, UA: %s", method, path, userAgent);

95

}

96

97

// Response manipulation

98

@Route(path = "/custom-response", methods = HttpMethod.GET)

99

public void customResponse(RoutingExchange exchange) {

100

exchange.response()

101

.putHeader("X-Custom-Header", "MyValue")

102

.putHeader("Cache-Control", "no-cache");

103

104

exchange.ok("Custom response with headers");

105

}

106

107

// Conditional responses

108

@Route(path = "/conditional/:id", methods = HttpMethod.GET)

109

public void conditionalResponse(@Param("id") String id, RoutingExchange exchange) {

110

if (id == null || id.trim().isEmpty()) {

111

exchange.notFound().end("Item not found");

112

return;

113

}

114

115

try {

116

long itemId = Long.parseLong(id);

117

if (itemId <= 0) {

118

exchange.serverError().end("Invalid item ID");

119

return;

120

}

121

exchange.ok("Item: " + itemId);

122

} catch (NumberFormatException e) {

123

exchange.serverError().end("Invalid item ID format");

124

}

125

}

126

127

// Query parameter access

128

@Route(path = "/search", methods = HttpMethod.GET)

129

public void search(RoutingExchange exchange) {

130

String query = exchange.getParam("q").orElse("");

131

String limit = exchange.getParam("limit").orElse("10");

132

String offset = exchange.getParam("offset").orElse("0");

133

134

if (query.isEmpty()) {

135

exchange.ok("No search query provided");

136

return;

137

}

138

139

exchange.ok(String.format("Search: %s (limit: %s, offset: %s)",

140

query, limit, offset));

141

}

142

}

143

```

144

145

### Low-Level Vert.x Access

146

147

Direct access to Vert.x objects for advanced request/response manipulation.

148

149

```java { .api }

150

// Access patterns for low-level operations

151

io.vertx.ext.web.RoutingContext context = exchange.context();

152

io.vertx.core.http.HttpServerRequest request = exchange.request();

153

io.vertx.core.http.HttpServerResponse response = exchange.response();

154

```

155

156

**Advanced Usage Examples:**

157

158

```java

159

@ApplicationScoped

160

public class AdvancedContextExamples {

161

162

// File upload handling

163

@Route(path = "/upload", methods = HttpMethod.POST, type = Route.HandlerType.BLOCKING)

164

public String handleFileUpload(RoutingExchange exchange) {

165

io.vertx.ext.web.RoutingContext context = exchange.context();

166

167

// Enable body handler for file uploads (configure in application)

168

Set<io.vertx.ext.web.FileUpload> uploads = context.fileUploads();

169

170

if (uploads.isEmpty()) {

171

return exchange.ok("No files uploaded");

172

}

173

174

StringBuilder result = new StringBuilder("Uploaded files:\n");

175

for (io.vertx.ext.web.FileUpload upload : uploads) {

176

result.append("- ").append(upload.fileName())

177

.append(" (").append(upload.size()).append(" bytes)\n");

178

}

179

180

return exchange.ok(result.toString());

181

}

182

183

// Cookie handling

184

@Route(path = "/set-cookie", methods = HttpMethod.POST)

185

public String setCookie(@Body CookieData cookieData, RoutingExchange exchange) {

186

io.vertx.core.http.HttpServerResponse response = exchange.response();

187

188

response.addCookie(io.vertx.core.http.Cookie.cookie(

189

cookieData.getName(),

190

cookieData.getValue()

191

).setMaxAge(3600).setPath("/"));

192

193

return exchange.ok("Cookie set: " + cookieData.getName());

194

}

195

196

// Session handling

197

@Route(path = "/session", methods = HttpMethod.GET)

198

public String handleSession(RoutingExchange exchange) {

199

io.vertx.ext.web.RoutingContext context = exchange.context();

200

io.vertx.ext.web.Session session = context.session();

201

202

if (session == null) {

203

return exchange.ok("No session available");

204

}

205

206

String visitCount = session.get("visitCount");

207

int count = visitCount != null ? Integer.parseInt(visitCount) : 0;

208

count++;

209

session.put("visitCount", String.valueOf(count));

210

211

return exchange.ok("Visit count: " + count);

212

}

213

214

// Request body streaming

215

@Route(path = "/stream-body", methods = HttpMethod.POST, type = Route.HandlerType.NORMAL)

216

public Uni<String> streamRequestBody(RoutingExchange exchange) {

217

io.vertx.core.http.HttpServerRequest request = exchange.request();

218

219

return request.body()

220

.map(buffer -> {

221

int size = buffer.length();

222

String preview = buffer.getString(0, Math.min(100, size));

223

return exchange.ok("Received " + size + " bytes, preview: " + preview);

224

});

225

}

226

}

227

228

// Supporting classes

229

public class CookieData {

230

private String name;

231

private String value;

232

233

public String getName() { return name; }

234

public void setName(String name) { this.name = name; }

235

public String getValue() { return value; }

236

public void setValue(String value) { this.value = value; }

237

}

238

```

239

240

### Response Status and Headers

241

242

Comprehensive response manipulation including status codes, headers, and content types.

243

244

```java

245

@ApplicationScoped

246

public class ResponseExamples {

247

248

// Custom status codes

249

@Route(path = "/custom-status/:code", methods = HttpMethod.GET)

250

public String customStatus(@Param("code") String statusCode, RoutingExchange exchange) {

251

try {

252

int code = Integer.parseInt(statusCode);

253

exchange.response().setStatusCode(code);

254

return exchange.ok("Status set to: " + code);

255

} catch (NumberFormatException e) {

256

return exchange.serverError();

257

}

258

}

259

260

// CORS headers

261

@Route(path = "/cors-enabled", methods = HttpMethod.GET)

262

public String corsEnabled(RoutingExchange exchange) {

263

io.vertx.core.http.HttpServerResponse response = exchange.response();

264

265

response.putHeader("Access-Control-Allow-Origin", "*")

266

.putHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE")

267

.putHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");

268

269

return exchange.ok("CORS headers set");

270

}

271

272

// Content-Type manipulation

273

@Route(path = "/xml-response", methods = HttpMethod.GET)

274

public String xmlResponse(RoutingExchange exchange) {

275

exchange.response().putHeader("Content-Type", "application/xml");

276

return exchange.ok("<?xml version=\"1.0\"?><root><message>Hello XML</message></root>");

277

}

278

279

// Cache control

280

@Route(path = "/cached-resource", methods = HttpMethod.GET)

281

public String cachedResource(RoutingExchange exchange) {

282

exchange.response()

283

.putHeader("Cache-Control", "public, max-age=3600")

284

.putHeader("ETag", "\"resource-v1\"");

285

286

return exchange.ok("This response is cacheable");

287

}

288

}

289

```

290

291

### Error Handling

292

293

Comprehensive error handling using the RoutingExchange interface.

294

295

```java

296

@ApplicationScoped

297

public class ErrorHandlingExamples {

298

299

// Validation with custom error responses

300

@Route(path = "/validate/:id", methods = HttpMethod.GET)

301

public String validateId(@Param("id") String id, RoutingExchange exchange) {

302

if (id == null || id.trim().isEmpty()) {

303

exchange.response().setStatusCode(400);

304

return exchange.ok("Bad Request: ID is required");

305

}

306

307

try {

308

long numericId = Long.parseLong(id);

309

if (numericId <= 0) {

310

exchange.response().setStatusCode(400);

311

return exchange.ok("Bad Request: ID must be positive");

312

}

313

return exchange.ok("Valid ID: " + numericId);

314

} catch (NumberFormatException e) {

315

exchange.response().setStatusCode(400);

316

return exchange.ok("Bad Request: ID must be numeric");

317

}

318

}

319

320

// Authentication check

321

@Route(path = "/protected-resource", methods = HttpMethod.GET)

322

public String protectedResource(RoutingExchange exchange) {

323

String authHeader = exchange.getHeader("Authorization").orElse("");

324

325

if (!authHeader.startsWith("Bearer ")) {

326

exchange.response().setStatusCode(401)

327

.putHeader("WWW-Authenticate", "Bearer");

328

return exchange.ok("Unauthorized: Bearer token required");

329

}

330

331

String token = authHeader.substring(7);

332

if (!isValidToken(token)) {

333

exchange.response().setStatusCode(403);

334

return exchange.ok("Forbidden: Invalid token");

335

}

336

337

return exchange.ok("Access granted to protected resource");

338

}

339

340

private boolean isValidToken(String token) {

341

// Token validation logic

342

return token.length() > 10;

343

}

344

}

345

```