or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

tessl/maven-org-http4s--http4s-ember-client

Ember HTTP client implementation for http4s with connection pooling and cross-platform support

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
mavenpkg:maven/org.http4s/http4s-ember-client_3@0.23.x

To install, run

npx @tessl/cli install tessl/maven-org-http4s--http4s-ember-client@0.23.0

0

# Http4s Ember Client

1

2

Http4s Ember Client is a high-performance HTTP client implementation for the http4s library, built on the ember networking library. It provides connection pooling, HTTP/2 support, cross-platform compatibility (JVM, JavaScript, Native), and comprehensive TLS configuration options.

3

4

## Package Information

5

6

- **Package Name**: http4s-ember-client_3

7

- **Package Type**: maven

8

- **Language**: Scala

9

- **Installation**: Add to your `build.sbt`:

10

```scala

11

libraryDependencies += "org.http4s" %% "http4s-ember-client" % "0.23.30"

12

```

13

14

## Core Imports

15

16

```scala

17

import org.http4s.ember.client.EmberClientBuilder

18

import org.http4s.ember.client.EmberClient

19

import cats.effect.IO

20

import org.http4s.client.Client

21

```

22

23

## Basic Usage

24

25

```scala

26

import org.http4s.ember.client.EmberClientBuilder

27

import cats.effect.IO

28

import org.http4s._

29

30

// Create a client with default settings

31

EmberClientBuilder.default[IO].build.use { client =>

32

// Make HTTP requests

33

val request = Request[IO](Method.GET, uri"https://api.example.com/users")

34

client.expect[String](request)

35

}

36

37

// Configure the client

38

EmberClientBuilder.default[IO]

39

.withMaxTotal(200)

40

.withTimeout(30.seconds)

41

.withHttp2

42

.build

43

.use { client =>

44

// Use configured client

45

}

46

```

47

48

## Architecture

49

50

The ember client is built around several key components:

51

52

- **EmberClientBuilder**: Fluent configuration API for setting up client parameters

53

- **EmberClient**: The main client implementation with connection pooling

54

- **Connection Pool**: Automatic connection reuse and management with configurable limits

55

- **Cross-Platform Support**: Single API that works on JVM, JavaScript, and Native platforms

56

- **HTTP/2 Support**: Optional HTTP/2 with server push promise handling

57

- **TLS Integration**: Full TLS/SSL support with endpoint verification

58

59

## Capabilities

60

61

### Client Builder

62

63

Configuration and creation of HTTP clients with comprehensive customization options.

64

65

```scala { .api }

66

/**

67

* Builder for configuring EmberClient instances with fluent API

68

*/

69

final class EmberClientBuilder[F[_]: Async: Network] private (

70

// Internal configuration fields omitted

71

) {

72

73

/** Create the configured HTTP client */

74

def build: Resource[F, Client[F]]

75

76

/** Set custom TLS context */

77

def withTLSContext(tlsContext: TLSContext[F]): EmberClientBuilder[F]

78

79

/** Use system default TLS context */

80

def withoutTLSContext: EmberClientBuilder[F]

81

82

/** Set socket group for connections */

83

def withSocketGroup(sg: SocketGroup[F]): EmberClientBuilder[F]

84

85

/** Set total maximum connections in pool */

86

def withMaxTotal(maxTotal: Int): EmberClientBuilder[F]

87

88

/** Set maximum connections per request key */

89

def withMaxPerKey(maxPerKey: RequestKey => Int): EmberClientBuilder[F]

90

91

/** Set idle timeout for pooled connections */

92

def withIdleTimeInPool(idleTimeInPool: Duration): EmberClientBuilder[F]

93

94

/** Set idle timeout on individual connections */

95

def withIdleConnectionTime(idleConnectionTime: Duration): EmberClientBuilder[F]

96

97

/** Set logger for client operations */

98

def withLogger(logger: Logger[F]): EmberClientBuilder[F]

99

100

/** Set chunk size for reading from sockets */

101

def withChunkSize(chunkSize: Int): EmberClientBuilder[F]

102

103

/** Set maximum response header size */

104

def withMaxResponseHeaderSize(maxResponseHeaderSize: Int): EmberClientBuilder[F]

105

106

/** Set header receive timeout */

107

def withTimeout(timeout: Duration): EmberClientBuilder[F]

108

109

/** Set additional socket options */

110

def withAdditionalSocketOptions(additionalSocketOptions: List[SocketOption]): EmberClientBuilder[F]

111

112

/** Set default User-Agent header */

113

def withUserAgent(userAgent: `User-Agent`): EmberClientBuilder[F]

114

115

/** Clear default User-Agent header */

116

def withoutUserAgent: EmberClientBuilder[F]

117

118

/** Enable/disable endpoint authentication verification */

119

def withCheckEndpointAuthentication(checkEndpointIdentification: Boolean): EmberClientBuilder[F]

120

121

/** Disable endpoint authentication verification */

122

def withoutCheckEndpointAuthentication: EmberClientBuilder[F]

123

124

/** Enable/disable Server Name Indication */

125

def withServerNameIndication(serverNameIndication: Boolean): EmberClientBuilder[F]

126

127

/** Disable Server Name Indication */

128

def withoutServerNameIndication: EmberClientBuilder[F]

129

130

/** Set retry policy for failed requests */

131

def withRetryPolicy(retryPolicy: RetryPolicy[F]): EmberClientBuilder[F]

132

133

/** Enable Unix socket support */

134

def withUnixSockets(unixSockets: UnixSockets[F]): EmberClientBuilder[F]

135

136

/** Enable HTTP/2 support */

137

def withHttp2: EmberClientBuilder[F]

138

139

/** Disable HTTP/2 support */

140

def withoutHttp2: EmberClientBuilder[F]

141

142

/** Set HTTP/2 push promise handler */

143

def withPushPromiseSupport(

144

f: (Request[fs2.Pure], F[Response[F]]) => F[Outcome[F, Throwable, Unit]]

145

): EmberClientBuilder[F]

146

147

/** Disable HTTP/2 push promise support */

148

def withoutPushPromiseSupport: EmberClientBuilder[F]

149

}

150

151

/**

152

* Factory methods for creating EmberClientBuilder instances

153

*/

154

object EmberClientBuilder {

155

/** Create builder with default configuration */

156

def default[F[_]: Async: Network]: EmberClientBuilder[F]

157

158

/** Create builder with default configuration (deprecated) */

159

@deprecated("Use default[F[_]: Async: Network] instead", "0.23.16")

160

def default[F[_]](async: Async[F]): EmberClientBuilder[F]

161

}

162

```

163

164

**Usage Examples:**

165

166

```scala

167

import org.http4s.ember.client.EmberClientBuilder

168

import cats.effect.IO

169

import scala.concurrent.duration._

170

171

// Basic client with defaults

172

val basicClient = EmberClientBuilder.default[IO].build

173

174

// Custom configuration

175

val customClient = EmberClientBuilder.default[IO]

176

.withMaxTotal(500)

177

.withMaxPerKey(_ => 50)

178

.withTimeout(45.seconds)

179

.withIdleConnectionTime(60.seconds)

180

.withChunkSize(64 * 1024)

181

.build

182

183

// HTTP/2 enabled client

184

val http2Client = EmberClientBuilder.default[IO]

185

.withHttp2

186

.withPushPromiseSupport { case (request, response) =>

187

// Handle server push promises

188

IO.pure(cats.effect.Outcome.Succeeded(IO.unit))

189

}

190

.build

191

192

// TLS configured client

193

val tlsClient = EmberClientBuilder.default[IO]

194

.withCheckEndpointAuthentication(true)

195

.withServerNameIndication(true)

196

.build

197

198

// Unix socket client

199

import fs2.io.net.unixsocket.UnixSockets

200

val unixClient = EmberClientBuilder.default[IO]

201

.withUnixSockets(UnixSockets.forAsync[IO])

202

.build

203

```

204

205

### HTTP Client Operations

206

207

Main HTTP client functionality for executing requests with connection pooling and state monitoring.

208

209

```scala { .api }

210

/**

211

* HTTP client implementation with connection pooling

212

*/

213

final class EmberClient[F[_]] private[client] (

214

private val client: Client[F],

215

private val pool: KeyPool[F, RequestKey, EmberConnection[F]]

216

)(implicit F: MonadCancelThrow[F]) extends DefaultClient[F] {

217

218

/** Execute HTTP request and return response resource */

219

def run(req: Request[F]): Resource[F, Response[F]]

220

221

/** Get current connection pool state */

222

def state: F[(Int, Map[RequestKey, Int])]

223

224

/** Default error handling for unsuccessful responses */

225

override def defaultOnError(req: Request[F])(resp: Response[F])(implicit G: Applicative[F]): F[Throwable]

226

}

227

```

228

229

**Usage Examples:**

230

231

```scala

232

import org.http4s._

233

import org.http4s.ember.client.EmberClientBuilder

234

import cats.effect.IO

235

236

// Basic request execution

237

EmberClientBuilder.default[IO].build.use { client =>

238

val request = Request[IO](Method.GET, uri"https://api.github.com/users/octocat")

239

240

// Get response as Resource

241

client.run(request).use { response =>

242

response.body.compile.toVector.map(bytes => new String(bytes.toArray))

243

}

244

245

// Or use convenience methods

246

client.expect[String](request)

247

}

248

249

// Monitor connection pool state

250

EmberClientBuilder.default[IO].build.use { client =>

251

for {

252

_ <- client.expect[String](Request[IO](Method.GET, uri"https://example.com"))

253

(totalConns, perKeyConns) <- client.state

254

_ <- IO.println(s"Total connections: $totalConns")

255

_ <- IO.println(s"Per-key connections: $perKeyConns")

256

} yield ()

257

}

258

259

// Handle different response types

260

EmberClientBuilder.default[IO].build.use { client =>

261

val jsonRequest = Request[IO](Method.GET, uri"https://api.github.com/users/octocat")

262

.withHeaders(Header.Raw(ci"Accept", "application/json"))

263

264

// Expect JSON response

265

import io.circe.Json

266

import org.http4s.circe._

267

client.expect[Json](jsonRequest)

268

}

269

```

270

271

## Default Configuration

272

273

### Connection Pool Settings

274

- **maxTotal**: 100 - Maximum total connections across all request keys

275

- **maxPerKey**: 100 - Maximum connections per individual request key

276

- **idleTimeInPool**: 30 seconds - How long connections can remain idle in the pool

277

278

### Network Settings

279

- **chunkSize**: 32KB (32,768 bytes) - Size of chunks when reading from sockets

280

- **maxResponseHeaderSize**: 4KB (4,096 bytes) - Maximum size for response headers

281

- **timeout**: 45 seconds - Maximum time to wait for response headers

282

- **idleConnectionTime**: 60 seconds - Idle timeout for individual connections

283

284

### Security Settings

285

- **checkEndpointIdentification**: true - Verify server identity against certificate

286

- **serverNameIndication**: true - Enable SNI for proper certificate selection

287

- **tlsContext**: System default SSL context

288

289

### Protocol Settings

290

- **enableHttp2**: false - HTTP/2 support disabled by default

291

- **pushPromiseSupport**: None - Server push promises disabled by default

292

- **userAgent**: "http4s-ember/{version}" - Default User-Agent header

293

294

### Retry Settings

295

- **retryPolicy**: RetryUntilFresh - Default retry strategy for failed requests

296

297

## Platform Support

298

299

### JVM Platform

300

- Full feature support including Unix sockets

301

- Uses Slf4j logging by default

302

- Supports all TLS features and socket options

303

304

### JavaScript Platform

305

- Available since version 0.23.5

306

- Uses NoOp logging by default

307

- HTTP/2 and TLS support available

308

309

### Native Platform

310

- Available since version 0.23.16

311

- Uses NoOp logging by default

312

- Full networking feature support (excluding Unix sockets)

313

314

## Types

315

316

```scala { .api }

317

// From cats-effect and fs2

318

import cats.effect.{Async, Resource, MonadCancelThrow}

319

import fs2.io.net.{Network, SocketGroup, SocketOption, TLSContext}

320

import fs2.io.net.unixsocket.{UnixSockets, UnixSocketAddress}

321

322

// From http4s

323

import org.http4s.{Request, Response, Method, Uri}

324

import org.http4s.client.{Client, RequestKey, RetryPolicy}

325

import org.http4s.headers.`User-Agent`

326

327

// From log4cats

328

import org.typelevel.log4cats.Logger

329

330

// From keypool

331

import org.typelevel.keypool.KeyPool

332

333

// Scala standard library

334

import scala.concurrent.duration.{Duration, FiniteDuration}

335

336

// Connection pool state: (total connections, connections per request key)

337

type PoolState = (Int, Map[RequestKey, Int])

338

339

// Push promise handler for HTTP/2

340

type PushPromiseHandler[F[_]] = (Request[fs2.Pure], F[Response[F]]) => F[cats.effect.Outcome[F, Throwable, Unit]]

341

```

342

343

## Error Handling

344

345

The ember client provides comprehensive error handling:

346

347

```scala

348

import org.http4s.ember.client.EmberClientBuilder

349

import cats.effect.IO

350

import org.http4s._

351

352

EmberClientBuilder.default[IO].build.use { client =>

353

val request = Request[IO](Method.GET, uri"https://httpbin.org/status/404")

354

355

client.run(request).use { response =>

356

if (response.status.isSuccess) {

357

response.body.compile.toVector

358

} else {

359

IO.raiseError(new RuntimeException(s"Request failed: ${response.status}"))

360

}

361

}

362

}

363

```

364

365

Common exceptions:

366

- **UnexpectedStatus**: When server returns non-success status codes

367

- **TimeoutException**: When requests exceed configured timeout

368

- **TLS exceptions**: For certificate verification failures

369

- **Connection exceptions**: For network connectivity issues