Asynchronous HTTP client for Play Framework with OAuth, OpenID, and SSL/TLS support
npx @tessl/cli install tessl/maven-com-typesafe-play--play-ws-2-10@2.4.0Play WS is a powerful asynchronous HTTP client library for the Play Framework. It provides comprehensive WebService client functionality built on top of the Ning AsyncHttpClient, supporting OAuth authentication, OpenID authentication, SSL/TLS configuration, and seamless integration with Play's reactive streaming model.
"com.typesafe.play" %% "play-ws" % "2.4.11""com.typesafe.play" % "play-java-ws_2.10" % "2.4.11"import play.api.libs.ws._
import play.api.libs.ws.ning._
import play.api.Application
import scala.concurrent.FutureFor dependency injection:
import javax.inject.Inject
import play.api.libs.ws.WSClient
class MyService @Inject()(ws: WSClient) {
// Use ws client
}import play.libs.ws.*;
import play.libs.F.Promise;
import java.util.concurrent.CompletionStage;For dependency injection:
import javax.inject.Inject;
import play.libs.ws.WSClient;
public class MyService {
private final WSClient ws;
@Inject
public MyService(WSClient ws) {
this.ws = ws;
}
}import play.api.libs.ws._
import play.api.Application
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
implicit val app: Application = // Your Play application
// Simple GET request
val futureResponse: Future[WSResponse] = WS.url("https://api.example.com/users").get()
// POST with JSON body
val jsonData = Json.obj("name" -> "John", "email" -> "john@example.com")
val postResponse: Future[WSResponse] = WS.url("https://api.example.com/users")
.withHeaders("Content-Type" -> "application/json")
.post(jsonData)
// Handle response
futureResponse.map { response =>
println(s"Status: ${response.status}")
println(s"Body: ${response.body}")
val jsonBody = response.json
}import play.libs.ws.*;
import play.libs.F.Promise;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import play.libs.Json;
// Simple GET request
Promise<WSResponse> responsePromise = WS.url("https://api.example.com/users").get();
// POST with JSON body
ObjectNode jsonData = Json.newObject();
jsonData.put("name", "John");
jsonData.put("email", "john@example.com");
Promise<WSResponse> postPromise = WS.url("https://api.example.com/users")
.setHeader("Content-Type", "application/json")
.post(jsonData);
// Handle response
responsePromise.map(response -> {
System.out.println("Status: " + response.getStatus());
System.out.println("Body: " + response.getBody());
JsonNode jsonBody = response.asJson();
return response;
});Play WS is built around several key components:
WS, WSClient, WSRequest, and WSResponse providing the main HTTP client APINingWSClient providing the actual HTTP implementation using Ning AsyncHttpClientCore HTTP client functionality for making RESTful API calls, handling responses, and managing connection settings.
object WS {
def client(implicit app: Application): WSClient
def url(url: String)(implicit app: Application): WSRequest
def clientUrl(url: String)(implicit client: WSClient): WSRequest
}
trait WSClient {
def underlying[T]: T
def url(url: String): WSRequest
def close(): Unit
}
trait WSRequest {
def get(): Future[WSResponse]
def post[T](body: T)(implicit wrt: Writeable[T]): Future[WSResponse]
def put[T](body: T)(implicit wrt: Writeable[T]): Future[WSResponse]
def patch[T](body: T)(implicit wrt: Writeable[T]): Future[WSResponse]
def delete(): Future[WSResponse]
def head(): Future[WSResponse]
def options(): Future[WSResponse]
}public class WS {
public static WSClient client()
public static WSRequest url(String url)
public static WSClient newClient(int port)
}
public interface WSClient extends Closeable {
WSRequest url(String url)
Object getUnderlying()
void close()
}
public interface WSRequest {
Promise<WSResponse> get()
Promise<WSResponse> post(Object body)
Promise<WSResponse> put(Object body)
Promise<WSResponse> patch(Object body)
Promise<WSResponse> delete()
Promise<WSResponse> head()
Promise<WSResponse> options()
Promise<WSResponse> execute()
WSRequest setHeader(String name, String value)
WSRequest setQueryParameter(String name, String value)
WSRequest setAuth(String username, String password, WSAuthScheme scheme)
WSRequest setBody(Object body)
WSRequest setMethod(String method)
}OAuth 1.0a authentication support for secure API access with consumer keys and request tokens.
case class OAuth(info: ServiceInfo, use10a: Boolean = true) {
def retrieveRequestToken(callbackURL: String): Either[OAuthException, RequestToken]
def retrieveAccessToken(token: RequestToken, verifier: String): Either[OAuthException, RequestToken]
def redirectUrl(token: String): String
}
case class OAuthCalculator(consumerKey: ConsumerKey, requestToken: RequestToken) extends WSSignatureCalculatorOpenID authentication support for identity verification and user attribute exchange.
object OpenID {
def redirectURL(
openID: String,
callbackURL: String,
axRequired: Seq[(String, String)] = Seq.empty,
axOptional: Seq[(String, String)] = Seq.empty,
realm: Option[String] = None
)(implicit app: Application): Future[String]
def verifiedId(implicit request: Request[_], app: Application): Future[UserInfo]
}Comprehensive SSL and TLS configuration system for secure HTTPS connections with custom certificates, protocols, and security settings.
case class SSLConfig(
default: Boolean = false,
protocol: String = "TLSv1.2",
enabledProtocols: Option[Seq[String]] = Some(Seq("TLSv1.2", "TLSv1.1", "TLSv1")),
enabledCipherSuites: Option[Seq[String]] = None,
keyManagerConfig: KeyManagerConfig = KeyManagerConfig(),
trustManagerConfig: TrustManagerConfig = TrustManagerConfig(),
debug: SSLDebugConfig = SSLDebugConfig(),
loose: SSLLooseConfig = SSLLooseConfig()
)Ning AsyncHttpClient-based implementation providing the actual HTTP transport layer with advanced configuration options.
case class NingWSClient(config: AsyncHttpClientConfig) extends WSClient {
def url(url: String): WSRequest
def close(): Unit
}
case class NingWSClientConfig(
wsClientConfig: WSClientConfig = WSClientConfig(),
allowPoolingConnection: Boolean = true,
maxConnectionsPerHost: Int = -1,
maxConnectionsTotal: Int = -1
)Testing utilities for HTTP client operations in Play applications.
trait WsTestClient {
def wsCall(call: Call)(implicit port: Port, client: WSClient): WSRequest
def wsUrl(url: String)(implicit port: Port, client: WSClient): WSRequest
def withClient[T](block: WSClient => T)(implicit port: play.api.http.Port): T
}trait 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]
}
trait WSCookie {
def name: String
def value: String
def domain: String
def path: Option[String]
def maxAge: Option[Long]
def secure: Boolean
def httpOnly: Boolean
}
sealed trait WSBody
case class InMemoryBody(bytes: Array[Byte]) extends WSBody
case class FileBody(file: File) extends WSBody
case class StreamedBody(bytes: Enumerator[Array[Byte]]) extends WSBody
case object EmptyBody extends WSBody
case class WSClientConfig(
connectionTimeout: Duration = 2.minutes,
idleTimeout: Duration = 2.minutes,
requestTimeout: Duration = 2.minutes,
followRedirects: Boolean = true,
useProxyProperties: Boolean = true,
userAgent: Option[String] = None,
compressionEnabled: Boolean = false,
ssl: SSLConfig = SSLConfig()
)
trait WSProxyServer {
def host: String
def port: Int
def protocol: Option[String]
def principal: Option[String]
def password: Option[String]
}
sealed trait WSAuthScheme
object WSAuthScheme {
case object BASIC extends WSAuthScheme
case object DIGEST extends WSAuthScheme
case object NTLM extends WSAuthScheme
case object SPNEGO extends WSAuthScheme
case object KERBEROS extends WSAuthScheme
case object NONE extends WSAuthScheme
}public interface WSResponse {
int getStatus()
String getStatusText()
String getHeader(String key)
Map<String, List<String>> getAllHeaders()
List<WSCookie> getCookies()
WSCookie getCookie(String name)
String getBody()
Document asXml()
JsonNode asJson()
InputStream getBodyAsStream()
byte[] asByteArray()
}
public interface WSCookie {
String getName()
String getValue()
String getDomain()
String getPath()
Long getMaxAge()
Boolean isSecure()
Boolean isHttpOnly()
}
public enum WSAuthScheme {
BASIC, DIGEST, NTLM, SPNEGO, KERBEROS, NONE
}