Square's meticulous HTTP client for Java and Kotlin
—
This document covers building HTTP requests and processing responses, including headers, bodies, and metadata handling.
Immutable HTTP request objects with builder pattern for construction.
class Request private constructor(
val url: HttpUrl,
val method: String,
val headers: Headers,
val body: RequestBody?,
val cacheUrlOverride: HttpUrl?
) {
val isHttps: Boolean
val cacheControl: CacheControl
fun header(name: String): String?
fun headers(name: String): List<String>
fun tag(): Any?
fun <T : Any> tag(type: KClass<T>): T?
fun <T> tag(type: Class<out T>): T?
fun newBuilder(): Builder
override fun toString(): String
}class Request.Builder {
fun url(url: HttpUrl): Builder
fun url(url: String): Builder
fun url(url: URL): Builder
fun header(name: String, value: String): Builder
fun addHeader(name: String, value: String): Builder
fun removeHeader(name: String): Builder
fun headers(headers: Headers): Builder
fun cacheControl(cacheControl: CacheControl): Builder
fun get(): Builder
fun head(): Builder
fun post(body: RequestBody): Builder
fun delete(body: RequestBody? = null): Builder
fun put(body: RequestBody): Builder
fun patch(body: RequestBody): Builder
fun method(method: String, body: RequestBody?): Builder
fun tag(tag: Any?): Builder
fun <T : Any> tag(type: KClass<T>, tag: T?): Builder
fun <T> tag(type: Class<out T>, tag: T?): Builder
fun build(): Request
}val request = Request.Builder()
.url("https://api.example.com/users/123")
.header("Accept", "application/json")
.header("User-Agent", "MyApp/1.0")
.build()val json = """{"name": "John Doe", "email": "john@example.com"}"""
val body = json.toRequestBody("application/json; charset=utf-8".toMediaType())
val request = Request.Builder()
.url("https://api.example.com/users")
.post(body)
.header("Content-Type", "application/json")
.build()val request = Request.Builder()
.url("https://api.example.com/data")
.addHeader("Authorization", "Bearer token123")
.addHeader("Accept", "application/json")
.addHeader("X-Custom-Header", "value1")
.addHeader("X-Custom-Header", "value2") // Multiple values
.build()Immutable HTTP response objects containing status, headers, and body.
class Response private constructor() : Closeable {
val request: Request
val protocol: Protocol
val code: Int
val message: String
val handshake: Handshake?
val headers: Headers
val body: ResponseBody
val networkResponse: Response?
val cacheResponse: Response?
val priorResponse: Response?
val receivedResponseAtMillis: Long
val sentRequestAtMillis: Long
val isSuccessful: Boolean // code in 200..299
val isRedirect: Boolean // code in 300..399
val cacheControl: CacheControl
fun header(name: String): String?
fun header(name: String, defaultValue: String): String
fun headers(name: String): List<String>
fun trailers(): Headers
fun peekBody(byteCount: Long): ResponseBody
fun challenges(): List<Challenge>
fun newBuilder(): Builder
override fun close()
override fun toString(): String
}class Response.Builder {
fun request(request: Request): Builder
fun protocol(protocol: Protocol): Builder
fun code(code: Int): Builder
fun message(message: String): Builder
fun handshake(handshake: Handshake?): Builder
fun header(name: String, value: String): Builder
fun addHeader(name: String, value: String): Builder
fun removeHeader(name: String): Builder
fun headers(headers: Headers): Builder
fun body(body: ResponseBody?): Builder
fun networkResponse(networkResponse: Response?): Builder
fun cacheResponse(cacheResponse: Response?): Builder
fun priorResponse(priorResponse: Response?): Builder
fun receivedResponseAtMillis(receivedResponseAtMillis: Long): Builder
fun sentRequestAtMillis(sentRequestAtMillis: Long): Builder
fun build(): Response
}client.newCall(request).execute().use { response ->
println("Status: ${response.code} ${response.message}")
println("Success: ${response.isSuccessful}")
println("Protocol: ${response.protocol}")
// Access headers
println("Content-Type: ${response.header("Content-Type")}")
println("Server: ${response.header("Server", "Unknown")}")
// Process body
if (response.isSuccessful) {
val responseBody = response.body?.string()
println("Body: $responseBody")
}
}val response = client.newCall(request).execute()
response.use {
when (it.code) {
200 -> println("Success: ${it.body?.string()}")
404 -> println("Not found")
401 -> println("Unauthorized")
in 500..599 -> println("Server error: ${it.message}")
else -> println("Unexpected response: ${it.code}")
}
}Immutable HTTP headers collection.
class Headers private constructor() : Iterable<Pair<String, String>> {
val size: Int
fun name(index: Int): String
fun value(index: Int): String
operator fun get(name: String): String?
fun get(name: String): String?
fun getDate(name: String): Date?
fun getInstant(name: String): Instant?
fun values(name: String): List<String>
fun byteCount(): Long
fun newBuilder(): Builder
fun toMultimap(): Map<String, List<String>>
override fun iterator(): Iterator<Pair<String, String>>
override fun equals(other: Any?): Boolean
override fun hashCode(): Int
override fun toString(): String
}class Headers.Builder {
fun add(name: String, value: String): Builder
fun add(name: String, value: Date): Builder
fun add(name: String, value: Instant): Builder
fun addUnsafeNonAscii(name: String, value: String): Builder
fun addAll(headers: Headers): Builder
fun set(name: String, value: String): Builder
fun set(name: String, value: Date): Builder
fun set(name: String, value: Instant): Builder
fun removeAll(name: String): Builder
operator fun get(name: String): String?
fun build(): Headers
}companion object Headers {
fun headersOf(vararg namesAndValues: String): Headers
fun headersOf(headers: Map<String, String>): Headers
}Abstract base class for request bodies.
abstract class RequestBody {
abstract fun contentType(): MediaType?
abstract fun contentLength(): Long
abstract fun writeTo(sink: BufferedSink)
open fun isDuplex(): Boolean = false
open fun isOneShot(): Boolean = false
companion object {
fun create(content: String, contentType: MediaType? = null): RequestBody
fun create(content: ByteString, contentType: MediaType? = null): RequestBody
fun create(content: ByteArray, contentType: MediaType? = null, offset: Int = 0, byteCount: Int = content.size): RequestBody
fun create(file: File, contentType: MediaType? = null): RequestBody
}
}fun String.toRequestBody(contentType: MediaType? = null): RequestBody
fun ByteString.toRequestBody(contentType: MediaType? = null): RequestBody
fun ByteArray.toRequestBody(contentType: MediaType? = null, offset: Int = 0, byteCount: Int = size): RequestBody
fun File.asRequestBody(contentType: MediaType? = null): RequestBodyAbstract base class for response bodies.
abstract class ResponseBody : Closeable {
abstract fun contentType(): MediaType?
abstract fun contentLength(): Long
abstract fun source(): BufferedSource
fun byteStream(): InputStream = source().inputStream()
fun bytes(): ByteArray
fun byteString(): ByteString
fun charStream(): Reader
fun string(): String
override fun close()
companion object {
fun create(content: String, contentType: MediaType? = null): ResponseBody
fun create(content: ByteString, contentType: MediaType? = null): ResponseBody
fun create(content: ByteArray, contentType: MediaType? = null): ResponseBody
fun create(content: BufferedSource, contentType: MediaType?, contentLength: Long): ResponseBody
}
}fun String.toResponseBody(contentType: MediaType? = null): ResponseBody
fun ByteString.toResponseBody(contentType: MediaType? = null): ResponseBody
fun ByteArray.toResponseBody(contentType: MediaType? = null): ResponseBody
fun BufferedSource.asResponseBody(contentType: MediaType? = null, contentLength: Long = -1L): ResponseBodyRepresents an RFC 2045 media type.
class MediaType private constructor() {
val type: String
val subtype: String
val charset: Charset?
fun charset(): Charset?
fun charset(defaultValue: Charset?): Charset?
override fun equals(other: Any?): Boolean
override fun hashCode(): Int
override fun toString(): String
companion object {
fun parse(string: String): MediaType?
fun get(string: String): MediaType
}
}fun String.toMediaType(): MediaType
fun String.toMediaTypeOrNull(): MediaType?// Creating media types
val jsonType = "application/json; charset=utf-8".toMediaType()
val textType = "text/plain".toMediaType()
val formType = "application/x-www-form-urlencoded".toMediaType()
// Using with request bodies
val jsonBody = """{"key": "value"}""".toRequestBody(jsonType)
val textBody = "Hello, World!".toRequestBody(textType)Install with Tessl CLI
npx tessl i tessl/maven-com-squareup-okhttp3--okhttp