CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-typesafe-play--play-ws-2-10

Asynchronous HTTP client for Play Framework with OAuth, OpenID, and SSL/TLS support

Pending
Overview
Eval results
Files

ning.mddocs/

Ning HTTP Client Implementation

Ning AsyncHttpClient-based implementation providing the actual HTTP transport layer with advanced configuration options. This is the default implementation used by Play WS for HTTP operations.

Capabilities

Ning WS Client

Main Ning-based WSClient implementation.

/**
 * WSClient implementation using Ning AsyncHttpClient
 * @param config AsyncHttpClient configuration
 */
case class NingWSClient(config: AsyncHttpClientConfig) extends WSClient {
  def underlying[T]: T
  def url(url: String): WSRequest
  def close(): Unit
}

/**
 * Ning WSClient factory
 */
object NingWSClient {
  /** Create client with default configuration */
  def apply(): NingWSClient
  
  /** Create client with custom configuration */
  def apply(config: NingWSClientConfig): NingWSClient
}

Basic Ning Client Usage:

import play.api.libs.ws.ning._

// Create client with default configuration
val client = NingWSClient()

// Use the client
val response = client.url("https://api.example.com/data").get()

// Always close the client when done
client.close()

Ning WS Request

Ning-specific WSRequest implementation with additional methods.

/**
 * Ning-specific WSRequest implementation
 */
case class NingWSRequest(
  client: NingWSClient,
  url: String,
  method: String = "GET",
  body: WSBody = EmptyBody,
  headers: Map[String, Seq[String]] = Map.empty,
  queryString: Map[String, Seq[String]] = Map.empty,
  calc: Option[WSSignatureCalculator] = None,
  auth: Option[(String, String, WSAuthScheme)] = None,
  followRedirects: Option[Boolean] = None,
  requestTimeout: Option[Int] = None,
  virtualHost: Option[String] = None,
  proxyServer: Option[WSProxyServer] = None
) extends WSRequest {
  
  // Additional Ning-specific methods
  /** Get current request headers */
  def requestHeaders: Map[String, Seq[String]]
  
  /** Get specific request header */
  def requestHeader(name: String): Option[String]
  
  /** Get current query parameters */
  def requestQueryParams: Map[String, Seq[String]]
  
  /** Get current URL (may include signature parameters) */
  def requestUrl: String
  
  /** Get request body as byte array */
  def getBody: Option[Array[Byte]]
}

Ning WS Response

Ning-specific WSResponse implementation.

/**
 * Ning-specific WSResponse implementation
 * @param ahcResponse Underlying AsyncHttpClient response
 */
case class NingWSResponse(ahcResponse: AHCResponse) extends WSResponse {
  def status: Int
  def statusText: String
  def header(key: String): Option[String]
  def allHeaders: Map[String, Seq[String]]
  def cookies: Seq[WSCookie]
  def cookie(name: String): Option[WSCookie]
  def body: String
  def xml: Elem
  def json: JsValue
  def bodyAsBytes: Array[Byte]
  def underlying[T]: T
}

Ning Client Configuration

Comprehensive configuration options for the Ning AsyncHttpClient.

/**
 * Ning WSClient configuration
 */
case class NingWSClientConfig(
  wsClientConfig: WSClientConfig = WSClientConfig(),
  allowPoolingConnection: Boolean = true,
  allowSslConnectionPool: Boolean = true,
  ioThreadMultiplier: Int = 2,
  maxConnectionsPerHost: Int = -1,
  maxConnectionsTotal: Int = -1,
  maxConnectionLifetime: Duration = Duration.Inf,
  idleConnectionInPoolTimeout: Duration = 1.minute,
  webSocketIdleTimeout: Duration = 15.minutes,
  maxNumberOfRedirects: Int = 5,
  maxRequestRetry: Int = 5,
  disableUrlEncoding: Boolean = false
)

Advanced Ning Configuration:

import scala.concurrent.duration._

val ningConfig = NingWSClientConfig(
  wsClientConfig = WSClientConfig(
    connectionTimeout = 10.seconds,
    requestTimeout = 30.seconds,
    followRedirects = true
  ),
  allowPoolingConnection = true,
  maxConnectionsPerHost = 20,
  maxConnectionsTotal = 100,
  maxConnectionLifetime = 5.minutes,
  idleConnectionInPoolTimeout = 2.minutes,
  maxNumberOfRedirects = 3,
  maxRequestRetry = 2
)

val client = NingWSClient(ningConfig)

Ning Configuration Factory

Factory for creating Ning configurations from WS configurations.

/**
 * Factory for creating Ning configurations
 */
object NingWSClientConfigFactory {
  /**
   * Create Ning configuration from WSClient configuration
   */
  def forClientConfig(config: WSClientConfig): NingWSClientConfig
}

AsyncHttpClient Configuration Builder

Builder for creating AsyncHttpClient configurations.

/**
 * Builder for AsyncHttpClient configuration
 */
class NingAsyncHttpClientConfigBuilder(ningConfig: NingWSClientConfig) {
  /** Configure the AsyncHttpClient builder */
  def configure(): AsyncHttpClientConfig.Builder
  
  /** Build the final configuration */
  def build(): AsyncHttpClientConfig
  
  /** Modify the underlying builder */
  def modifyUnderlying(
    modify: AsyncHttpClientConfig.Builder => AsyncHttpClientConfig.Builder
  ): NingAsyncHttpClientConfigBuilder
}

Custom AsyncHttpClient Configuration:

import com.ning.http.client.AsyncHttpClientConfig

val builder = new NingAsyncHttpClientConfigBuilder(ningConfig)
  .modifyUnderlying { ahcBuilder =>
    ahcBuilder
      .setUserAgent("MyApp/1.0")
      .setCompressionEnforced(true)
      .setFollowRedirect(true)
  }

val ahcConfig = builder.build()
val client = NingWSClient(ahcConfig)

Dependency Injection Support

Play Framework dependency injection support for Ning WS client.

/**
 * Play module for Ning WS dependency injection
 */
class NingWSModule extends Module {
  def bindings(environment: Environment, configuration: Configuration): Seq[Binding[_]]
}

/**
 * Injectable WSAPI implementation using Ning
 */
class NingWSAPI @Inject()(client: WSClient) extends WSAPI {
  def client: WSClient
  def url(url: String): WSRequest
}

/**
 * Components trait for manual dependency injection
 */
trait NingWSComponents {
  def wsClient: WSClient
  def wsApi: WSAPI
}

Manual Dependency Injection Setup:

import play.api.libs.ws.ning._

trait MyApplicationComponents extends NingWSComponents {
  // Provide WSClient implementation
  lazy val wsClient: WSClient = {
    val config = NingWSClientConfig()
    NingWSClient(config)
  }
  
  // Provide WSAPI implementation  
  lazy val wsApi: WSAPI = new NingWSAPI(wsClient)
  
  // Don't forget to close client on app shutdown
  override def applicationLifecycle: ApplicationLifecycle = {
    val lifecycle = super.applicationLifecycle
    lifecycle.addStopHook(() => Future.successful(wsClient.close()))
    lifecycle
  }
}

Connection Pool Management

Managing connection pools with Ning client.

// Configuration for connection pooling
val poolConfig = NingWSClientConfig(
  allowPoolingConnection = true,
  allowSslConnectionPool = true,
  maxConnectionsPerHost = 50,      // Max connections per host
  maxConnectionsTotal = 200,       // Max total connections
  maxConnectionLifetime = 10.minutes,  // Max connection age
  idleConnectionInPoolTimeout = 5.minutes  // Idle timeout
)

val client = NingWSClient(poolConfig)

// The client will automatically manage the connection pool
// Connections are reused for better performance
val response1 = client.url("https://api.example.com/endpoint1").get()
val response2 = client.url("https://api.example.com/endpoint2").get()

// Both requests can reuse the same connection to api.example.com

Request Retry Configuration

Configure automatic request retries for failed requests.

val retryConfig = NingWSClientConfig(
  maxRequestRetry = 3,  // Retry failed requests up to 3 times
  maxNumberOfRedirects = 5  // Follow up to 5 redirects
)

val client = NingWSClient(retryConfig)

// This request will be automatically retried on failure
val response = client.url("https://unreliable-api.com/data").get()

WebSocket Configuration

Configure WebSocket idle timeout (for when using WS client with WebSockets).

val wsConfig = NingWSClientConfig(
  webSocketIdleTimeout = 30.minutes  // Close idle WebSocket connections after 30 minutes
)

val client = NingWSClient(wsConfig)

Performance Tuning

Optimize Ning client for different scenarios.

High Throughput Configuration:

val highThroughputConfig = NingWSClientConfig(
  wsClientConfig = WSClientConfig(
    connectionTimeout = 5.seconds,
    requestTimeout = 30.seconds
  ),
  allowPoolingConnection = true,
  allowSslConnectionPool = true,
  ioThreadMultiplier = 4,  // More I/O threads for high concurrency
  maxConnectionsPerHost = 100,
  maxConnectionsTotal = 500,
  maxConnectionLifetime = 30.minutes,
  idleConnectionInPoolTimeout = 10.minutes
)

Low Latency Configuration:

val lowLatencyConfig = NingWSClientConfig(
  wsClientConfig = WSClientConfig(
    connectionTimeout = 1.second,
    requestTimeout = 5.seconds
  ),
  allowPoolingConnection = true,
  maxConnectionsPerHost = 10,  // Smaller pool for faster connection reuse
  maxConnectionsTotal = 50,
  idleConnectionInPoolTimeout = 1.minute,  // Shorter idle timeout
  maxRequestRetry = 1  // Fewer retries for lower latency
)

Resource-Constrained Configuration:

val resourceConstrainedConfig = NingWSClientConfig(
  allowPoolingConnection = true,
  maxConnectionsPerHost = 5,   // Limit connections
  maxConnectionsTotal = 20,    // Lower total pool size
  maxConnectionLifetime = 2.minutes,  // Shorter connection lifetime
  idleConnectionInPoolTimeout = 30.seconds,  // Quick idle cleanup
  ioThreadMultiplier = 1  // Fewer threads
)

Custom Request/Response Processing

Access underlying Ning objects for advanced processing.

client.url("https://api.example.com/data").get().map { response =>
  // Access underlying Ning response
  val ningResponse = response.underlying[com.ning.http.client.Response]
  
  // Get additional response information
  val responseTime = ningResponse.getResponseTime
  val uri = ningResponse.getUri
  val contentLength = ningResponse.getContentLength
  
  println(s"Response time: ${responseTime}ms")
  println(s"Content length: $contentLength bytes")
}

Complete Example: Production Ning Setup

import play.api.libs.ws.ning._
import play.api.libs.ws.ssl._
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global

// Create production-ready Ning configuration
val productionConfig = NingWSClientConfig(
  wsClientConfig = WSClientConfig(
    connectionTimeout = 10.seconds,
    idleTimeout = 60.seconds,
    requestTimeout = 30.seconds,
    followRedirects = true,
    useProxyProperties = true,
    userAgent = Some("MyApp/2.0"),
    compressionEnabled = true,
    ssl = SSLConfig(
      protocol = "TLSv1.2",
      enabledProtocols = Some(Seq("TLSv1.2"))
    )
  ),
  allowPoolingConnection = true,
  allowSslConnectionPool = true,
  ioThreadMultiplier = 2,
  maxConnectionsPerHost = 20,
  maxConnectionsTotal = 100,
  maxConnectionLifetime = 10.minutes,
  idleConnectionInPoolTimeout = 5.minutes,
  maxNumberOfRedirects = 3,
  maxRequestRetry = 2,
  disableUrlEncoding = false
)

// Create and use the client
val client = NingWSClient(productionConfig)

// Make requests
val future = for {
  response1 <- client.url("https://api.service1.com/data").get()
  response2 <- client.url("https://api.service2.com/data").get()
} yield {
  (response1.json, response2.json)
}

future.map { case (json1, json2) =>
  // Process responses
  println("Data retrieved successfully")
}.recover { case ex =>
  println(s"Request failed: ${ex.getMessage}")
}.andThen { case _ =>
  // Always clean up resources
  client.close()
}

Install with Tessl CLI

npx tessl i tessl/maven-com-typesafe-play--play-ws-2-10

docs

http-client.md

index.md

ning.md

oauth.md

openid.md

ssl.md

testing.md

tile.json