CtrlK
BlogDocsLog inGet started
Tessl Logo

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

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

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

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

docs

index.md

tile.json