or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

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

index.mddocs/

Http4s Ember Client

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.

Package Information

  • Package Name: http4s-ember-client_3
  • Package Type: maven
  • Language: Scala
  • Installation: Add to your build.sbt:
    libraryDependencies += "org.http4s" %% "http4s-ember-client" % "0.23.30"

Core Imports

import org.http4s.ember.client.EmberClientBuilder
import org.http4s.ember.client.EmberClient
import cats.effect.IO
import org.http4s.client.Client

Basic Usage

import org.http4s.ember.client.EmberClientBuilder
import cats.effect.IO
import org.http4s._

// Create a client with default settings
EmberClientBuilder.default[IO].build.use { client =>
  // Make HTTP requests
  val request = Request[IO](Method.GET, uri"https://api.example.com/users")
  client.expect[String](request)
}

// Configure the client
EmberClientBuilder.default[IO]
  .withMaxTotal(200)
  .withTimeout(30.seconds)
  .withHttp2
  .build
  .use { client =>
    // Use configured client
  }

Architecture

The ember client is built around several key components:

  • EmberClientBuilder: Fluent configuration API for setting up client parameters
  • EmberClient: The main client implementation with connection pooling
  • Connection Pool: Automatic connection reuse and management with configurable limits
  • Cross-Platform Support: Single API that works on JVM, JavaScript, and Native platforms
  • HTTP/2 Support: Optional HTTP/2 with server push promise handling
  • TLS Integration: Full TLS/SSL support with endpoint verification

Capabilities

Client Builder

Configuration and creation of HTTP clients with comprehensive customization options.

/**
 * Builder for configuring EmberClient instances with fluent API
 */
final class EmberClientBuilder[F[_]: Async: Network] private (
  // Internal configuration fields omitted
) {
  
  /** Create the configured HTTP client */
  def build: Resource[F, Client[F]]
  
  /** Set custom TLS context */
  def withTLSContext(tlsContext: TLSContext[F]): EmberClientBuilder[F]
  
  /** Use system default TLS context */
  def withoutTLSContext: EmberClientBuilder[F]
  
  /** Set socket group for connections */
  def withSocketGroup(sg: SocketGroup[F]): EmberClientBuilder[F]
  
  /** Set total maximum connections in pool */
  def withMaxTotal(maxTotal: Int): EmberClientBuilder[F]
  
  /** Set maximum connections per request key */
  def withMaxPerKey(maxPerKey: RequestKey => Int): EmberClientBuilder[F]
  
  /** Set idle timeout for pooled connections */
  def withIdleTimeInPool(idleTimeInPool: Duration): EmberClientBuilder[F]
  
  /** Set idle timeout on individual connections */
  def withIdleConnectionTime(idleConnectionTime: Duration): EmberClientBuilder[F]
  
  /** Set logger for client operations */
  def withLogger(logger: Logger[F]): EmberClientBuilder[F]
  
  /** Set chunk size for reading from sockets */
  def withChunkSize(chunkSize: Int): EmberClientBuilder[F]
  
  /** Set maximum response header size */
  def withMaxResponseHeaderSize(maxResponseHeaderSize: Int): EmberClientBuilder[F]
  
  /** Set header receive timeout */
  def withTimeout(timeout: Duration): EmberClientBuilder[F]
  
  /** Set additional socket options */
  def withAdditionalSocketOptions(additionalSocketOptions: List[SocketOption]): EmberClientBuilder[F]
  
  /** Set default User-Agent header */
  def withUserAgent(userAgent: `User-Agent`): EmberClientBuilder[F]
  
  /** Clear default User-Agent header */
  def withoutUserAgent: EmberClientBuilder[F]
  
  /** Enable/disable endpoint authentication verification */
  def withCheckEndpointAuthentication(checkEndpointIdentification: Boolean): EmberClientBuilder[F]
  
  /** Disable endpoint authentication verification */
  def withoutCheckEndpointAuthentication: EmberClientBuilder[F]
  
  /** Enable/disable Server Name Indication */
  def withServerNameIndication(serverNameIndication: Boolean): EmberClientBuilder[F]
  
  /** Disable Server Name Indication */
  def withoutServerNameIndication: EmberClientBuilder[F]
  
  /** Set retry policy for failed requests */
  def withRetryPolicy(retryPolicy: RetryPolicy[F]): EmberClientBuilder[F]
  
  /** Enable Unix socket support */
  def withUnixSockets(unixSockets: UnixSockets[F]): EmberClientBuilder[F]
  
  /** Enable HTTP/2 support */
  def withHttp2: EmberClientBuilder[F]
  
  /** Disable HTTP/2 support */
  def withoutHttp2: EmberClientBuilder[F]
  
  /** Set HTTP/2 push promise handler */
  def withPushPromiseSupport(
    f: (Request[fs2.Pure], F[Response[F]]) => F[Outcome[F, Throwable, Unit]]
  ): EmberClientBuilder[F]
  
  /** Disable HTTP/2 push promise support */
  def withoutPushPromiseSupport: EmberClientBuilder[F]
}

/**
 * Factory methods for creating EmberClientBuilder instances
 */
object EmberClientBuilder {
  /** Create builder with default configuration */
  def default[F[_]: Async: Network]: EmberClientBuilder[F]
  
  /** Create builder with default configuration (deprecated) */
  @deprecated("Use default[F[_]: Async: Network] instead", "0.23.16")
  def default[F[_]](async: Async[F]): EmberClientBuilder[F]
}

Usage Examples:

import org.http4s.ember.client.EmberClientBuilder
import cats.effect.IO
import scala.concurrent.duration._

// Basic client with defaults
val basicClient = EmberClientBuilder.default[IO].build

// Custom configuration
val customClient = EmberClientBuilder.default[IO]
  .withMaxTotal(500)
  .withMaxPerKey(_ => 50)
  .withTimeout(45.seconds)
  .withIdleConnectionTime(60.seconds)
  .withChunkSize(64 * 1024)
  .build

// HTTP/2 enabled client
val http2Client = EmberClientBuilder.default[IO]
  .withHttp2
  .withPushPromiseSupport { case (request, response) =>
    // Handle server push promises
    IO.pure(cats.effect.Outcome.Succeeded(IO.unit))
  }
  .build

// TLS configured client
val tlsClient = EmberClientBuilder.default[IO]
  .withCheckEndpointAuthentication(true)
  .withServerNameIndication(true)
  .build

// Unix socket client
import fs2.io.net.unixsocket.UnixSockets
val unixClient = EmberClientBuilder.default[IO]
  .withUnixSockets(UnixSockets.forAsync[IO])
  .build

HTTP Client Operations

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

/**
 * HTTP client implementation with connection pooling
 */
final class EmberClient[F[_]] private[client] (
  private val client: Client[F],
  private val pool: KeyPool[F, RequestKey, EmberConnection[F]]
)(implicit F: MonadCancelThrow[F]) extends DefaultClient[F] {
  
  /** Execute HTTP request and return response resource */
  def run(req: Request[F]): Resource[F, Response[F]]
  
  /** Get current connection pool state */
  def state: F[(Int, Map[RequestKey, Int])]
  
  /** Default error handling for unsuccessful responses */
  override def defaultOnError(req: Request[F])(resp: Response[F])(implicit G: Applicative[F]): F[Throwable]
}

Usage Examples:

import org.http4s._
import org.http4s.ember.client.EmberClientBuilder
import cats.effect.IO

// Basic request execution
EmberClientBuilder.default[IO].build.use { client =>
  val request = Request[IO](Method.GET, uri"https://api.github.com/users/octocat")
  
  // Get response as Resource
  client.run(request).use { response =>
    response.body.compile.toVector.map(bytes => new String(bytes.toArray))
  }
  
  // Or use convenience methods
  client.expect[String](request)
}

// Monitor connection pool state
EmberClientBuilder.default[IO].build.use { client =>
  for {
    _ <- client.expect[String](Request[IO](Method.GET, uri"https://example.com"))
    (totalConns, perKeyConns) <- client.state
    _ <- IO.println(s"Total connections: $totalConns")
    _ <- IO.println(s"Per-key connections: $perKeyConns")
  } yield ()
}

// Handle different response types
EmberClientBuilder.default[IO].build.use { client =>
  val jsonRequest = Request[IO](Method.GET, uri"https://api.github.com/users/octocat")
    .withHeaders(Header.Raw(ci"Accept", "application/json"))
  
  // Expect JSON response  
  import io.circe.Json
  import org.http4s.circe._
  client.expect[Json](jsonRequest)
}

Default Configuration

Connection Pool Settings

  • maxTotal: 100 - Maximum total connections across all request keys
  • maxPerKey: 100 - Maximum connections per individual request key
  • idleTimeInPool: 30 seconds - How long connections can remain idle in the pool

Network Settings

  • chunkSize: 32KB (32,768 bytes) - Size of chunks when reading from sockets
  • maxResponseHeaderSize: 4KB (4,096 bytes) - Maximum size for response headers
  • timeout: 45 seconds - Maximum time to wait for response headers
  • idleConnectionTime: 60 seconds - Idle timeout for individual connections

Security Settings

  • checkEndpointIdentification: true - Verify server identity against certificate
  • serverNameIndication: true - Enable SNI for proper certificate selection
  • tlsContext: System default SSL context

Protocol Settings

  • enableHttp2: false - HTTP/2 support disabled by default
  • pushPromiseSupport: None - Server push promises disabled by default
  • userAgent: "http4s-ember/{version}" - Default User-Agent header

Retry Settings

  • retryPolicy: RetryUntilFresh - Default retry strategy for failed requests

Platform Support

JVM Platform

  • Full feature support including Unix sockets
  • Uses Slf4j logging by default
  • Supports all TLS features and socket options

JavaScript Platform

  • Available since version 0.23.5
  • Uses NoOp logging by default
  • HTTP/2 and TLS support available

Native Platform

  • Available since version 0.23.16
  • Uses NoOp logging by default
  • Full networking feature support (excluding Unix sockets)

Types

// From cats-effect and fs2
import cats.effect.{Async, Resource, MonadCancelThrow}
import fs2.io.net.{Network, SocketGroup, SocketOption, TLSContext}
import fs2.io.net.unixsocket.{UnixSockets, UnixSocketAddress}

// From http4s
import org.http4s.{Request, Response, Method, Uri}
import org.http4s.client.{Client, RequestKey, RetryPolicy}
import org.http4s.headers.`User-Agent`

// From log4cats
import org.typelevel.log4cats.Logger

// From keypool  
import org.typelevel.keypool.KeyPool

// Scala standard library
import scala.concurrent.duration.{Duration, FiniteDuration}

// Connection pool state: (total connections, connections per request key)
type PoolState = (Int, Map[RequestKey, Int])

// Push promise handler for HTTP/2
type PushPromiseHandler[F[_]] = (Request[fs2.Pure], F[Response[F]]) => F[cats.effect.Outcome[F, Throwable, Unit]]

Error Handling

The ember client provides comprehensive error handling:

import org.http4s.ember.client.EmberClientBuilder
import cats.effect.IO
import org.http4s._

EmberClientBuilder.default[IO].build.use { client =>
  val request = Request[IO](Method.GET, uri"https://httpbin.org/status/404")
  
  client.run(request).use { response =>
    if (response.status.isSuccess) {
      response.body.compile.toVector
    } else {
      IO.raiseError(new RuntimeException(s"Request failed: ${response.status}"))
    }
  }
}

Common exceptions:

  • UnexpectedStatus: When server returns non-success status codes
  • TimeoutException: When requests exceed configured timeout
  • TLS exceptions: For certificate verification failures
  • Connection exceptions: For network connectivity issues