A scriptable web server for testing HTTP clients with support for HTTP/1.1, HTTP/2, WebSockets, and SSL/TLS
—
Request inspection and verification functionality for validating client behavior. RecordedRequest provides access to all request details including headers, body content, metadata, and connection information, enabling comprehensive testing of HTTP client implementations.
Represents an HTTP request received by MockWebServer with all request details captured for verification.
/**
* Represents an HTTP request received by MockWebServer. Immutable object containing
* all request details captured during processing.
*/
class RecordedRequest @JvmOverloads constructor(
requestLine: String,
headers: Headers,
chunkSizes: List<Int>,
bodySize: Long,
body: Buffer,
sequenceNumber: Int,
socket: Socket
)Access basic request information including HTTP method, path, and protocol version.
/**
* Full HTTP request line (method + path + version)
*/
val requestLine: String
/**
* HTTP method (GET, POST, PUT, DELETE, etc.)
*/
val method: String?
/**
* Request path including query parameters
*/
val path: String?
/**
* Parsed request URL with all components
*/
val requestUrl: HttpUrl?
/**
* String representation (returns request line)
*/
fun toString(): StringUsage Examples:
val server = MockWebServer()
server.enqueue(MockResponse().setBody("OK"))
server.start()
// Client makes request...
val client = OkHttpClient()
val request = Request.Builder()
.url(server.url("/api/users?page=1"))
.post("data".toRequestBody())
.build()
client.newCall(request).execute()
// Verify request details
val recordedRequest = server.takeRequest()
assertEquals("POST /api/users?page=1 HTTP/1.1", recordedRequest.requestLine)
assertEquals("POST", recordedRequest.method)
assertEquals("/api/users?page=1", recordedRequest.path)
assertEquals("http", recordedRequest.requestUrl?.scheme)
assertEquals("users", recordedRequest.requestUrl?.pathSegments?.get(1))
assertEquals("1", recordedRequest.requestUrl?.queryParameter("page"))Comprehensive header inspection and verification.
/**
* Request headers as Headers object
*/
val headers: Headers
/**
* Get first header value with given name (case-insensitive)
* @param name Header name to retrieve
* @returns First header value or null if not found
*/
fun getHeader(name: String): String?Usage Examples:
val server = MockWebServer()
server.enqueue(MockResponse().setBody("OK"))
server.start()
// Client makes request with headers...
val request = Request.Builder()
.url(server.url("/api/data"))
.addHeader("Authorization", "Bearer token123")
.addHeader("Content-Type", "application/json")
.addHeader("X-Client-Version", "1.2.3")
.build()
client.newCall(request).execute()
// Verify headers
val recordedRequest = server.takeRequest()
assertEquals("Bearer token123", recordedRequest.getHeader("Authorization"))
assertEquals("application/json", recordedRequest.getHeader("Content-Type"))
assertEquals("1.2.3", recordedRequest.getHeader("X-Client-Version"))
// Check all headers
assertTrue(recordedRequest.headers.names().contains("User-Agent"))
assertEquals(4, recordedRequest.headers.size()) // Including User-Agent added by OkHttp
// Case-insensitive header access
assertEquals("Bearer token123", recordedRequest.getHeader("authorization"))
assertEquals("Bearer token123", recordedRequest.getHeader("AUTHORIZATION"))Access and verify request body content with size information.
/**
* Request body as Buffer (may be truncated based on bodyLimit)
*/
val body: Buffer
/**
* Total body size before any truncation
*/
val bodySize: LongUsage Examples:
val server = MockWebServer()
server.enqueue(MockResponse().setBody("OK"))
server.start()
// Client sends JSON data
val jsonData = """{"name": "John", "email": "john@example.com"}"""
val request = Request.Builder()
.url(server.url("/api/users"))
.post(jsonData.toRequestBody("application/json".toMediaType()))
.build()
client.newCall(request).execute()
// Verify request body
val recordedRequest = server.takeRequest()
assertEquals(jsonData, recordedRequest.body.readUtf8())
assertEquals(jsonData.length.toLong(), recordedRequest.bodySize)
// For large bodies, check truncation
server.bodyLimit = 100 // Limit to 100 bytes
// ... make request with large body ...
val largeRequest = server.takeRequest()
assertTrue(largeRequest.bodySize > 100) // Original size
assertTrue(largeRequest.body.size <= 100) // Truncated sizeInformation about chunked transfer encoding when used.
/**
* Chunk sizes if chunked transfer encoding was used
*/
val chunkSizes: List<Int>Usage Examples:
// When client uses chunked encoding
val recordedRequest = server.takeRequest()
if (recordedRequest.chunkSizes.isNotEmpty()) {
println("Request used chunked encoding")
println("Chunk sizes: ${recordedRequest.chunkSizes}")
println("Total chunks: ${recordedRequest.chunkSizes.size}")
}Information about the connection and request sequencing.
/**
* Request sequence number on this connection (0-based)
*/
val sequenceNumber: Int
/**
* IOException if request decoding failed
*/
val failure: IOException?Usage Examples:
val server = MockWebServer()
server.enqueue(MockResponse().setBody("Response 1"))
server.enqueue(MockResponse().setBody("Response 2"))
server.start()
// Client makes multiple requests on same connection
val client = OkHttpClient()
val request1 = Request.Builder().url(server.url("/first")).build()
val request2 = Request.Builder().url(server.url("/second")).build()
client.newCall(request1).execute()
client.newCall(request2).execute()
// Verify sequence numbers
val firstRequest = server.takeRequest()
val secondRequest = server.takeRequest()
assertEquals(0, firstRequest.sequenceNumber) // First request on connection
assertEquals(1, secondRequest.sequenceNumber) // Second request on same connection
// Check for decoding failures
assertNull(firstRequest.failure)
assertNull(secondRequest.failure)SSL/TLS handshake and encryption information when HTTPS is used.
/**
* TLS handshake information if HTTPS was used
*/
val handshake: Handshake?
/**
* TLS version used for HTTPS requests
*/
val tlsVersion: TlsVersion?Usage Examples:
val server = MockWebServer()
val sslContext = SSLContext.getInstance("TLS")
sslContext.init(null, arrayOf(getTrustAllManager()), SecureRandom())
server.useHttps(sslContext.socketFactory, false)
server.enqueue(MockResponse().setBody("Secure response"))
server.start()
// Client makes HTTPS request
val request = Request.Builder()
.url(server.url("/secure").newBuilder().scheme("https").build())
.build()
client.newCall(request).execute()
// Verify SSL/TLS information
val recordedRequest = server.takeRequest()
assertNotNull(recordedRequest.handshake)
assertNotNull(recordedRequest.tlsVersion)
println("TLS Version: ${recordedRequest.tlsVersion}")
println("Cipher Suite: ${recordedRequest.handshake?.cipherSuite}")
println("Peer Certificates: ${recordedRequest.handshake?.peerCertificates?.size}")Typical patterns for comprehensive request verification.
Complete Request Verification:
fun verifyRequest(
recordedRequest: RecordedRequest,
expectedMethod: String,
expectedPath: String,
expectedHeaders: Map<String, String> = emptyMap(),
expectedBody: String? = null
) {
assertEquals(expectedMethod, recordedRequest.method)
assertEquals(expectedPath, recordedRequest.path)
expectedHeaders.forEach { (name, value) ->
assertEquals(value, recordedRequest.getHeader(name))
}
expectedBody?.let { body ->
assertEquals(body, recordedRequest.body.readUtf8())
}
}
// Usage
val recordedRequest = server.takeRequest()
verifyRequest(
recordedRequest,
expectedMethod = "POST",
expectedPath = "/api/users",
expectedHeaders = mapOf(
"Content-Type" to "application/json",
"Authorization" to "Bearer token123"
),
expectedBody = """{"name": "John", "email": "john@example.com"}"""
)Multiple Request Verification:
val server = MockWebServer()
repeat(3) { server.enqueue(MockResponse().setBody("OK")) }
server.start()
// Client makes multiple requests...
// Verify all requests
val requests = mutableListOf<RecordedRequest>()
repeat(3) {
requests.add(server.takeRequest())
}
assertEquals("GET", requests[0].method)
assertEquals("POST", requests[1].method)
assertEquals("DELETE", requests[2].method)
// Verify request sequence
requests.forEachIndexed { index, request ->
assertEquals(index, request.sequenceNumber)
}Install with Tessl CLI
npx tessl i tessl/maven-com-squareup-okhttp3--mockwebserver