or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

aop.mdconfiguration.mddependency-injection.mdfunctions.mdhttp-client.mdhttp-server.mdindex.mdmanagement.mdmessaging.mdreactive.mdretry.mdscheduling.mdwebsocket.md

http-client.mddocs/

0

# HTTP Client

1

2

Micronaut's HTTP client provides both programmatic and declarative APIs for making HTTP requests with reactive support, service discovery integration, and comprehensive configuration options.

3

4

## Capabilities

5

6

### Declarative Client

7

8

Create HTTP clients using interfaces with declarative annotations.

9

10

```java { .api }

11

/**

12

* Declarative HTTP client interface

13

*/

14

@Client("/api/users")

15

public interface UserClient {

16

17

@Get("/{id}")

18

Single<User> getUser(Long id);

19

20

@Get

21

Single<List<User>> getAllUsers(@QueryValue Optional<String> filter);

22

23

@Post

24

Single<User> createUser(@Body @Valid User user);

25

26

@Put("/{id}")

27

Single<User> updateUser(Long id, @Body @Valid User user);

28

29

@Delete("/{id}")

30

Completable deleteUser(Long id);

31

}

32

33

/**

34

* Client with custom headers and error handling

35

*/

36

@Client(value = "${external.api.url}",

37

configuration = ApiClientConfiguration.class)

38

@Header(name = "User-Agent", value = "MyApp/1.0")

39

public interface ExternalApiClient {

40

41

@Get("/data/{id}")

42

@Header(name = "X-API-Key", value = "${api.key}")

43

Single<ApiResponse> getData(String id);

44

45

@Post("/webhooks")

46

@Header(name = "Content-Type", value = "application/json")

47

Completable sendWebhook(@Body WebhookPayload payload);

48

49

@Get("/health")

50

@Retryable(attempts = "3", delay = "1s")

51

Single<HealthStatus> checkHealth();

52

}

53

```

54

55

### Programmatic Client

56

57

Create and use HTTP clients programmatically for dynamic requests.

58

59

```java { .api }

60

/**

61

* Programmatic HTTP client usage

62

*/

63

@Singleton

64

public class ApiService {

65

private final HttpClient httpClient;

66

67

public ApiService(@Client("${api.base-url}") HttpClient httpClient) {

68

this.httpClient = httpClient;

69

}

70

71

public Single<User> getUser(Long userId) {

72

HttpRequest<Object> request = HttpRequest.GET("/users/" + userId)

73

.header("Authorization", "Bearer " + getToken());

74

75

return httpClient.retrieve(request, User.class);

76

}

77

78

public Single<User> createUser(User user) {

79

HttpRequest<User> request = HttpRequest.POST("/users", user)

80

.contentType(MediaType.APPLICATION_JSON);

81

82

return httpClient.retrieve(request, User.class);

83

}

84

85

public Single<HttpResponse<User>> createUserWithResponse(User user) {

86

HttpRequest<User> request = HttpRequest.POST("/users", user);

87

88

return httpClient.exchange(request, User.class);

89

}

90

}

91

```

92

93

### Reactive Streaming

94

95

Stream large responses or handle real-time data with reactive types.

96

97

```java { .api }

98

/**

99

* Streaming HTTP client

100

*/

101

@Client("/api/stream")

102

public interface StreamingClient {

103

104

@Get(value = "/events", processes = MediaType.TEXT_EVENT_STREAM)

105

Flowable<ServerSentEvent<Event>> streamEvents();

106

107

@Get("/large-data")

108

Flowable<ByteBuffer<?>> streamLargeData();

109

110

@Post("/upload")

111

Single<UploadResult> uploadStream(@Body Flowable<ByteBuffer<?>> data);

112

}

113

114

/**

115

* JSON streaming

116

*/

117

@Singleton

118

public class StreamingService {

119

private final StreamingHttpClient streamingClient;

120

121

public StreamingService(@Client("${api.url}") StreamingHttpClient streamingClient) {

122

this.streamingClient = streamingClient;

123

}

124

125

public Flowable<User> streamUsers() {

126

HttpRequest<Object> request = HttpRequest.GET("/users/stream");

127

return streamingClient.jsonStream(request, User.class);

128

}

129

130

public Flowable<ByteBuffer<?>> downloadFile(String fileId) {

131

HttpRequest<Object> request = HttpRequest.GET("/files/" + fileId);

132

return streamingClient.dataStream(request);

133

}

134

}

135

```

136

137

### Client Configuration

138

139

Configure HTTP clients with timeouts, connection settings, and custom behavior.

140

141

```java { .api }

142

/**

143

* Client configuration class

144

*/

145

@ConfigurationProperties("http-client.api")

146

public class ApiClientConfiguration extends HttpClientConfiguration {

147

148

@Override

149

public Duration getReadTimeout() {

150

return Duration.ofSeconds(30);

151

}

152

153

@Override

154

public Duration getConnectTimeout() {

155

return Duration.ofSeconds(10);

156

}

157

158

@Override

159

public Integer getMaxContentLength() {

160

return 1024 * 1024 * 10; // 10MB

161

}

162

}

163

164

/**

165

* Custom client configuration factory

166

*/

167

@Factory

168

public class HttpClientFactory {

169

170

@Bean

171

@Named("secure-client")

172

public HttpClient createSecureClient() {

173

return HttpClient.create("https://secure-api.example.com")

174

.configuration(config -> {

175

config.readTimeout(Duration.ofSeconds(60));

176

config.followRedirects(true);

177

config.maxContentLength(1024 * 1024 * 50); // 50MB

178

});

179

}

180

181

@Bean

182

@Named("fast-client")

183

public HttpClient createFastClient() {

184

return HttpClient.create("https://fast-api.example.com")

185

.configuration(config -> {

186

config.readTimeout(Duration.ofSeconds(5));

187

config.connectTimeout(Duration.ofSeconds(2));

188

config.connectionPoolSize(20);

189

});

190

}

191

}

192

```

193

194

### Client Filters

195

196

Add request/response filtering for authentication, logging, and other cross-cutting concerns.

197

198

```java { .api }

199

/**

200

* Client filter for authentication

201

*/

202

@Filter("/api/**")

203

public class AuthenticationClientFilter implements HttpClientFilter {

204

205

@Override

206

public Publisher<? extends HttpResponse<?>> doFilter(MutableHttpRequest<?> request,

207

ClientFilterChain chain) {

208

String token = getAuthToken();

209

request.header("Authorization", "Bearer " + token);

210

return chain.proceed(request);

211

}

212

213

private String getAuthToken() {

214

// Get authentication token

215

return "token";

216

}

217

}

218

219

/**

220

* Logging client filter

221

*/

222

@Filter("/**")

223

public class LoggingClientFilter implements HttpClientFilter {

224

225

@Override

226

public Publisher<? extends HttpResponse<?>> doFilter(MutableHttpRequest<?> request,

227

ClientFilterChain chain) {

228

log.info("Sending request: {} {}", request.getMethod(), request.getUri());

229

230

return chain.proceed(request)

231

.doOnNext(response ->

232

log.info("Received response: {} for {} {}",

233

response.getStatus(), request.getMethod(), request.getUri()))

234

.doOnError(error ->

235

log.error("Request failed: {} {} - {}",

236

request.getMethod(), request.getUri(), error.getMessage()));

237

}

238

}

239

```

240

241

### Error Handling

242

243

Handle HTTP errors and network failures with custom error handling logic.

244

245

```java { .api }

246

/**

247

* Client with error handling

248

*/

249

@Client("/api")

250

public interface ResilientClient {

251

252

@Get("/data")

253

@Retryable(attempts = "3", delay = "2s", multiplier = "1.5")

254

Single<Data> getData();

255

256

@Get("/unreliable")

257

@CircuitBreaker(attempts = "5", openStatusTimeout = "1m", resetTimeout = "30s")

258

Single<String> getUnreliableData();

259

260

@Fallback

261

static Single<String> getUnreliableDataFallback() {

262

return Single.just("fallback-data");

263

}

264

}

265

266

/**

267

* Custom error handling

268

*/

269

@Singleton

270

public class ApiClientService {

271

private final HttpClient httpClient;

272

273

public ApiClientService(@Client("${api.url}") HttpClient httpClient) {

274

this.httpClient = httpClient;

275

}

276

277

public Single<User> getUserWithErrorHandling(Long id) {

278

HttpRequest<Object> request = HttpRequest.GET("/users/" + id);

279

280

return httpClient.exchange(request, User.class)

281

.flatMap(response -> {

282

if (response.getStatus().getCode() == 404) {

283

return Single.error(new UserNotFoundException(id));

284

} else if (response.getStatus().getCode() >= 400) {

285

return Single.error(new ApiException(response.getStatus()));

286

}

287

return Single.just(response.body());

288

})

289

.onErrorResumeNext(throwable -> {

290

if (throwable instanceof ConnectException) {

291

return Single.error(new ServiceUnavailableException());

292

}

293

return Single.error(throwable);

294

});

295

}

296

}

297

```

298

299

### Service Discovery Integration

300

301

Integrate with service discovery systems for dynamic service resolution.

302

303

```java { .api }

304

/**

305

* Client with service discovery

306

*/

307

@Client(id = "user-service", path = "/api/users")

308

public interface UserServiceClient {

309

310

@Get("/{id}")

311

Single<User> getUser(Long id);

312

313

@Get

314

Single<List<User>> getAllUsers();

315

}

316

317

/**

318

* Load balancing configuration

319

*/

320

@ConfigurationProperties("http-client.user-service")

321

public class UserServiceClientConfiguration extends HttpClientConfiguration {

322

323

@Override

324

public Duration getReadTimeout() {

325

return Duration.ofSeconds(15);

326

}

327

328

// Load balancer configuration

329

public LoadBalancer getLoadBalancer() {

330

return LoadBalancer.ROUND_ROBIN;

331

}

332

}

333

```

334

335

### File Upload and Download

336

337

Handle file operations with progress tracking and streaming support.

338

339

```java { .api }

340

/**

341

* File operations client

342

*/

343

@Client("/api/files")

344

public interface FileClient {

345

346

@Post(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA)

347

Single<FileUploadResult> uploadFile(@Part CompletedFileUpload file,

348

@Part("metadata") FileMetadata metadata);

349

350

@Get("/{fileId}")

351

Single<byte[]> downloadFile(String fileId);

352

353

@Get(value = "/{fileId}/stream")

354

Flowable<ByteBuffer<?>> streamFile(String fileId);

355

356

@Delete("/{fileId}")

357

Completable deleteFile(String fileId);

358

}

359

360

/**

361

* Large file handling

362

*/

363

@Singleton

364

public class FileService {

365

private final StreamingHttpClient streamingClient;

366

367

public FileService(@Client("${file.service.url}") StreamingHttpClient streamingClient) {

368

this.streamingClient = streamingClient;

369

}

370

371

public Single<String> uploadLargeFile(File file) {

372

HttpRequest<Object> request = HttpRequest.POST("/upload", file)

373

.contentType(MediaType.APPLICATION_OCTET_STREAM)

374

.header("Content-Length", String.valueOf(file.length()));

375

376

return streamingClient.retrieve(request, String.class);

377

}

378

379

public void downloadLargeFile(String fileId, File destination) {

380

HttpRequest<Object> request = HttpRequest.GET("/files/" + fileId);

381

382

streamingClient.dataStream(request)

383

.subscribe(buffer -> {

384

// Write buffer to file

385

writeToFile(buffer, destination);

386

});

387

}

388

}

389

```

390

391

## Types

392

393

```java { .api }

394

// Core client interfaces

395

public interface HttpClient extends Closeable, LifeCycle<HttpClient> {

396

<I, O> Publisher<HttpResponse<O>> exchange(HttpRequest<I> request,

397

Argument<O> bodyType);

398

<I, O> Publisher<HttpResponse<O>> exchange(HttpRequest<I> request,

399

Class<O> bodyType);

400

<I, O> Publisher<O> retrieve(HttpRequest<I> request, Argument<O> bodyType);

401

<I, O> Publisher<O> retrieve(HttpRequest<I> request, Class<O> bodyType);

402

403

BlockingHttpClient toBlocking();

404

static HttpClient create(URL url);

405

}

406

407

public interface StreamingHttpClient extends HttpClient {

408

<I> Publisher<ByteBuffer<?>> dataStream(HttpRequest<I> request);

409

<I> Publisher<Map<String, Object>> jsonStream(HttpRequest<I> request);

410

<I, O> Publisher<O> jsonStream(HttpRequest<I> request, Argument<O> type);

411

}

412

413

public interface BlockingHttpClient extends Closeable, LifeCycle<BlockingHttpClient> {

414

<I, O> HttpResponse<O> exchange(HttpRequest<I> request, Class<O> bodyType);

415

<I, O> O retrieve(HttpRequest<I> request, Class<O> bodyType);

416

String retrieve(String uri);

417

}

418

419

// Client configuration

420

public class HttpClientConfiguration {

421

public Duration getReadTimeout();

422

public Duration getConnectTimeout();

423

public Duration getConnectionPoolIdleTimeout();

424

public Integer getMaxContentLength();

425

public boolean isFollowRedirects();

426

public ProxyConfiguration getProxyConfiguration();

427

public HttpVersion getHttpVersion();

428

}

429

430

// Client filtering

431

public interface HttpClientFilter extends ClientFilter {

432

Publisher<? extends HttpResponse<?>> doFilter(MutableHttpRequest<?> request,

433

ClientFilterChain chain);

434

}

435

436

public interface ClientFilterChain {

437

Publisher<? extends HttpResponse<?>> proceed(MutableHttpRequest<?> request);

438

}

439

440

// Request creation

441

public final class HttpRequest {

442

public static <T> MutableHttpRequest<T> GET(String uri);

443

public static <T> MutableHttpRequest<T> POST(String uri, T body);

444

public static <T> MutableHttpRequest<T> PUT(String uri, T body);

445

public static <T> MutableHttpRequest<T> DELETE(String uri);

446

public static <T> MutableHttpRequest<T> HEAD(String uri);

447

public static <T> MutableHttpRequest<T> OPTIONS(String uri);

448

public static <T> MutableHttpRequest<T> PATCH(String uri, T body);

449

public static <T> MutableHttpRequest<T> TRACE(String uri);

450

}

451

452

public interface MutableHttpRequest<B> extends HttpRequest<B>, MutableHttpMessage<B> {

453

MutableHttpRequest<B> cookie(Cookie cookie);

454

MutableHttpRequest<B> uri(URI uri);

455

MutableHttpRequest<B> header(CharSequence name, CharSequence value);

456

MutableHttpRequest<B> headers(Map<CharSequence, CharSequence> headers);

457

MutableHttpRequest<B> contentType(MediaType mediaType);

458

MutableHttpRequest<B> accept(MediaType... mediaTypes);

459

MutableHttpRequest<B> basicAuth(String username, String password);

460

MutableHttpRequest<B> bearerAuth(String token);

461

}

462

463

// Service discovery types

464

public enum LoadBalancer {

465

ROUND_ROBIN,

466

RANDOM,

467

STICKY

468

}

469

470

public interface ServiceDiscoveryClient {

471

Publisher<List<ServiceInstance>> getInstances(String serviceId);

472

String getDescription();

473

}

474

```