Asynchronous HTTP client for Play Framework with OAuth, OpenID, and SSL/TLS support
—
Core HTTP client functionality for making RESTful API calls, handling responses, and managing connection settings. The Play WS HTTP client provides both static factory methods and dependency injection support for both Scala and Java APIs.
Main entry point for creating HTTP requests using the application's default client.
/**
* Static object providing HTTP client access
*/
object WS {
/** Get or create the application's default WSClient */
def client(implicit app: Application): WSClient
/** Create a request using the application's default client */
def url(url: String)(implicit app: Application): WSRequest
/** Create a request using a magnet pattern */
def url(magnet: WSRequestMagnet): WSRequest
/** Create a request with an explicit client */
def clientUrl(url: String)(implicit client: WSClient): WSRequest
}Usage Examples:
import play.api.libs.ws.WS
import play.api.Application
import scala.concurrent.ExecutionContext.Implicits.global
implicit val app: Application = // Your Play application
// Create a simple GET request
val response = WS.url("https://api.example.com/users").get()
// POST with form data
val formData = Map("name" -> Seq("John"), "email" -> Seq("john@example.com"))
val postResponse = WS.url("https://api.example.com/users").post(formData)HTTP client interface for creating requests and managing connections.
/**
* HTTP client interface
*/
trait WSClient {
/** Get the underlying implementation (cast explicitly to desired type) */
def underlying[T]: T
/** Create a request builder for the given URL */
def url(url: String): WSRequest
/** Release client resources */
def close(): Unit
}Dependency Injection Usage:
import javax.inject.Inject
import play.api.libs.ws.WSClient
class MyService @Inject()(ws: WSClient) {
def fetchUser(id: String): Future[User] = {
ws.url(s"https://api.example.com/users/$id")
.get()
.map(response => Json.parse(response.body).as[User])
}
}Main entry point for creating HTTP requests using the Java API.
/**
* Static class providing HTTP client access for Java
*/
public class WS {
/** Get the application's default WSClient */
public static WSClient client()
/** Create a request using the application's default client */
public static WSRequest url(String url)
/** Create a test client bound to a specific port */
public static WSClient newClient(int port)
}Usage Examples:
import play.libs.ws.*;
import play.libs.F.Promise;
// Create a simple GET request
Promise<WSResponse> response = WS.url("https://api.example.com/users").get();
// POST with form data
Map<String, String> formData = new HashMap<>();
formData.put("name", "John");
formData.put("email", "john@example.com");
Promise<WSResponse> postResponse = WS.url("https://api.example.com/users").post(formData);HTTP client interface for creating requests and managing connections.
/**
* HTTP client interface for Java
*/
public interface WSClient extends Closeable {
/** Get the underlying implementation */
Object getUnderlying()
/** Create a request builder for the given URL */
WSRequest url(String url)
/** Release client resources */
void close()
}Dependency Injection Usage:
import javax.inject.Inject;
import play.libs.ws.WSClient;
public class MyService {
private final WSClient ws;
@Inject
public MyService(WSClient ws) {
this.ws = ws;
}
public Promise<User> fetchUser(String id) {
return ws.url("https://api.example.com/users/" + id)
.get()
.map(response -> Json.fromJson(response.asJson(), User.class));
}
}HTTP request builder providing fluent API for configuring and executing requests.
/**
* HTTP request builder with fluent configuration API
*/
trait WSRequest {
// Properties
def url: String
def method: String
def body: WSBody
def headers: Map[String, Seq[String]]
def queryString: Map[String, Seq[String]]
// Configuration methods
def withHeaders(hdrs: (String, String)*): WSRequest
def withQueryString(parameters: (String, String)*): WSRequest
def withFollowRedirects(follow: Boolean): WSRequest
def withRequestTimeout(timeout: Long): WSRequest
def withVirtualHost(vh: String): WSRequest
def withProxyServer(proxyServer: WSProxyServer): WSRequest
def withBody(body: WSBody): WSRequest
def withMethod(method: String): WSRequest
def withAuth(username: String, password: String, scheme: WSAuthScheme): WSRequest
def sign(calc: WSSignatureCalculator): WSRequest
// HTTP method execution
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]
def execute(): Future[WSResponse]
// Streaming support
def stream(): Future[(WSResponseHeaders, Enumerator[Array[Byte]])]
}Configuration Examples:
import play.api.libs.ws._
import scala.concurrent.duration._
// Configure request with headers, timeout, and query parameters
val request = WS.url("https://api.example.com/search")
.withHeaders(
"Authorization" -> "Bearer token123",
"Content-Type" -> "application/json"
)
.withQueryString(
"q" -> "scala",
"limit" -> "10"
)
.withRequestTimeout(5.seconds.toMillis)
.withFollowRedirects(false)
// Execute the configured request
val response = request.get()HTTP request builder providing fluent API for configuring and executing requests in Java.
/**
* HTTP request builder with fluent configuration API for Java
*/
public interface WSRequest {
// Properties
String getUrl()
String getMethod()
// Configuration methods
WSRequest setHeader(String name, String value)
WSRequest setQueryParameter(String name, String value)
WSRequest setAuth(String username, String password)
WSRequest setAuth(String username, String password, WSAuthScheme scheme)
WSRequest setFollowRedirects(boolean followRedirects)
WSRequest setVirtualHost(String virtualHost)
WSRequest setTimeout(long timeout)
WSRequest setBody(Object body)
WSRequest setMethod(String method)
WSRequest sign(WSSignatureCalculator calculator)
// HTTP method execution
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()
}Configuration Examples:
import play.libs.ws.*;
import java.util.concurrent.TimeUnit;
// Configure request with headers, timeout, and query parameters
WSRequest request = WS.url("https://api.example.com/search")
.setHeader("Authorization", "Bearer token123")
.setHeader("Content-Type", "application/json")
.setQueryParameter("q", "java")
.setQueryParameter("limit", "10")
.setTimeout(TimeUnit.SECONDS.toMillis(5))
.setFollowRedirects(false);
// Execute the configured request
Promise<WSResponse> response = request.get();HTTP response interface providing access to status, headers, cookies, and body content.
/**
* HTTP response interface
*/
trait WSResponse {
// Status information
def status: Int
def statusText: String
// Headers and cookies
def header(key: String): Option[String]
def allHeaders: Map[String, Seq[String]]
def cookies: Seq[WSCookie]
def cookie(name: String): Option[WSCookie]
// Body content access
def body: String
def xml: Elem
def json: JsValue
def bodyAsBytes: Array[Byte]
// Underlying implementation access
def underlying[T]: T
}Response Handling Examples:
import play.api.libs.json._
import scala.xml.Elem
WS.url("https://api.example.com/data").get().map { response =>
// Check status
if (response.status == 200) {
// Access different body formats
val textBody: String = response.body
val jsonBody: JsValue = response.json
val xmlBody: Elem = response.xml
val bytesBody: Array[Byte] = response.bodyAsBytes
// Access headers
val contentType = response.header("Content-Type")
val allHeaders = response.allHeaders
// Access cookies
val sessionCookie = response.cookie("JSESSIONID")
val allCookies = response.cookies
}
}HTTP response interface providing access to status, headers, cookies, and body content in Java.
/**
* HTTP response interface for Java
*/
public interface WSResponse {
// Status information
int getStatus()
String getStatusText()
// Headers and cookies
String getHeader(String key)
Map<String, List<String>> getAllHeaders()
List<WSCookie> getCookies()
WSCookie getCookie(String name)
// Body content access
String getBody()
Document asXml()
JsonNode asJson()
InputStream getBodyAsStream()
byte[] asByteArray()
// Underlying implementation access
Object getUnderlying()
}Response Handling Examples:
import play.libs.ws.*;
import com.fasterxml.jackson.databind.JsonNode;
import org.w3c.dom.Document;
WS.url("https://api.example.com/data").get().map(response -> {
// Check status
if (response.getStatus() == 200) {
// Access different body formats
String textBody = response.getBody();
JsonNode jsonBody = response.asJson();
Document xmlBody = response.asXml();
byte[] bytesBody = response.asByteArray();
// Access headers
String contentType = response.getHeader("Content-Type");
Map<String, List<String>> allHeaders = response.getAllHeaders();
// Access cookies
WSCookie sessionCookie = response.getCookie("JSESSIONID");
List<WSCookie> allCookies = response.getCookies();
}
return response;
});Different body types for HTTP requests.
/**
* Base trait for request bodies
*/
sealed trait WSBody
/** In-memory byte array body */
case class InMemoryBody(bytes: Array[Byte]) extends WSBody
/** File-based body */
case class FileBody(file: File) extends WSBody
/** Streaming body using iteratees */
case class StreamedBody(bytes: Enumerator[Array[Byte]]) extends WSBody
/** Empty body */
case object EmptyBody extends WSBodyBody Usage Examples:
import java.io.File
import play.api.libs.iteratee.Enumerator
// JSON body (automatically converted to InMemoryBody)
val jsonBody = Json.obj("name" -> "John", "age" -> 25)
WS.url("https://api.example.com/users").post(jsonBody)
// File upload
val file = new File("/path/to/file.txt")
WS.url("https://api.example.com/upload").post(FileBody(file))
// Form data
val formData = Map("field1" -> Seq("value1"), "field2" -> Seq("value2"))
WS.url("https://api.example.com/form").post(formData)
// Raw bytes
val bytes = "Hello World".getBytes("UTF-8")
WS.url("https://api.example.com/data").post(InMemoryBody(bytes))Available authentication schemes for HTTP requests.
/**
* Authentication scheme marker trait
*/
trait WSAuthScheme
/**
* Authentication schemes
*/
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
}Authentication Examples:
// Basic authentication
WS.url("https://api.example.com/secure")
.withAuth("username", "password", WSAuthScheme.BASIC)
.get()
// Digest authentication
WS.url("https://api.example.com/secure")
.withAuth("username", "password", WSAuthScheme.DIGEST)
.get()HTTP proxy server configuration.
/**
* Proxy server configuration
*/
trait WSProxyServer {
def host: String
def port: Int
def protocol: Option[String]
def principal: Option[String]
def password: Option[String]
def ntlmDomain: Option[String]
def encoding: Option[String]
def nonProxyHosts: Option[Seq[String]]
}
/**
* Default proxy server implementation
*/
case class DefaultWSProxyServer(
host: String,
port: Int,
protocol: Option[String] = None,
principal: Option[String] = None,
password: Option[String] = None,
ntlmDomain: Option[String] = None,
encoding: Option[String] = None,
nonProxyHosts: Option[Seq[String]] = None
) extends WSProxyServerProxy Usage:
val proxy = DefaultWSProxyServer("proxy.company.com", 8080)
WS.url("https://external-api.com/data")
.withProxyServer(proxy)
.get()Cookie handling in responses.
/**
* HTTP cookie interface
*/
trait WSCookie {
def underlying[T]: T
def domain: String
def name: Option[String]
def value: Option[String]
def path: String
def expires: Option[Long] // deprecated
def maxAge: Option[Int]
def secure: Boolean
}Response header information.
/**
* HTTP response headers
*/
trait WSResponseHeaders {
def status: Int
def headers: Map[String, Seq[String]]
}
/**
* Default response headers implementation
*/
case class DefaultWSResponseHeaders(
status: Int,
headers: Map[String, Seq[String]]
) extends WSResponseHeadersFor handling large responses with streaming.
// Streaming response handling
WS.url("https://api.example.com/large-file").stream().map {
case (headers, body) =>
// Process headers
println(s"Content-Length: ${headers.headers.get("Content-Length")}")
// Process body stream
body |>>> Iteratee.foreach[Array[Byte]] { chunk =>
// Process each chunk
println(s"Received ${chunk.length} bytes")
}
}Install with Tessl CLI
npx tessl i tessl/maven-com-typesafe-play--play-ws-2-10