0
# Request Verification
1
2
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.
3
4
## Capabilities
5
6
### RecordedRequest Class
7
8
Represents an HTTP request received by MockWebServer with all request details captured for verification.
9
10
```kotlin { .api }
11
/**
12
* Represents an HTTP request received by MockWebServer. Immutable object containing
13
* all request details captured during processing.
14
*/
15
class RecordedRequest @JvmOverloads constructor(
16
requestLine: String,
17
headers: Headers,
18
chunkSizes: List<Int>,
19
bodySize: Long,
20
body: Buffer,
21
sequenceNumber: Int,
22
socket: Socket
23
)
24
```
25
26
### Request Line and Method
27
28
Access basic request information including HTTP method, path, and protocol version.
29
30
```kotlin { .api }
31
/**
32
* Full HTTP request line (method + path + version)
33
*/
34
val requestLine: String
35
36
/**
37
* HTTP method (GET, POST, PUT, DELETE, etc.)
38
*/
39
val method: String?
40
41
/**
42
* Request path including query parameters
43
*/
44
val path: String?
45
46
/**
47
* Parsed request URL with all components
48
*/
49
val requestUrl: HttpUrl?
50
51
/**
52
* String representation (returns request line)
53
*/
54
fun toString(): String
55
```
56
57
**Usage Examples:**
58
59
```kotlin
60
val server = MockWebServer()
61
server.enqueue(MockResponse().setBody("OK"))
62
server.start()
63
64
// Client makes request...
65
val client = OkHttpClient()
66
val request = Request.Builder()
67
.url(server.url("/api/users?page=1"))
68
.post("data".toRequestBody())
69
.build()
70
client.newCall(request).execute()
71
72
// Verify request details
73
val recordedRequest = server.takeRequest()
74
assertEquals("POST /api/users?page=1 HTTP/1.1", recordedRequest.requestLine)
75
assertEquals("POST", recordedRequest.method)
76
assertEquals("/api/users?page=1", recordedRequest.path)
77
assertEquals("http", recordedRequest.requestUrl?.scheme)
78
assertEquals("users", recordedRequest.requestUrl?.pathSegments?.get(1))
79
assertEquals("1", recordedRequest.requestUrl?.queryParameter("page"))
80
```
81
82
### Headers Access
83
84
Comprehensive header inspection and verification.
85
86
```kotlin { .api }
87
/**
88
* Request headers as Headers object
89
*/
90
val headers: Headers
91
92
/**
93
* Get first header value with given name (case-insensitive)
94
* @param name Header name to retrieve
95
* @returns First header value or null if not found
96
*/
97
fun getHeader(name: String): String?
98
```
99
100
**Usage Examples:**
101
102
```kotlin
103
val server = MockWebServer()
104
server.enqueue(MockResponse().setBody("OK"))
105
server.start()
106
107
// Client makes request with headers...
108
val request = Request.Builder()
109
.url(server.url("/api/data"))
110
.addHeader("Authorization", "Bearer token123")
111
.addHeader("Content-Type", "application/json")
112
.addHeader("X-Client-Version", "1.2.3")
113
.build()
114
115
client.newCall(request).execute()
116
117
// Verify headers
118
val recordedRequest = server.takeRequest()
119
assertEquals("Bearer token123", recordedRequest.getHeader("Authorization"))
120
assertEquals("application/json", recordedRequest.getHeader("Content-Type"))
121
assertEquals("1.2.3", recordedRequest.getHeader("X-Client-Version"))
122
123
// Check all headers
124
assertTrue(recordedRequest.headers.names().contains("User-Agent"))
125
assertEquals(4, recordedRequest.headers.size()) // Including User-Agent added by OkHttp
126
127
// Case-insensitive header access
128
assertEquals("Bearer token123", recordedRequest.getHeader("authorization"))
129
assertEquals("Bearer token123", recordedRequest.getHeader("AUTHORIZATION"))
130
```
131
132
### Body Content Verification
133
134
Access and verify request body content with size information.
135
136
```kotlin { .api }
137
/**
138
* Request body as Buffer (may be truncated based on bodyLimit)
139
*/
140
val body: Buffer
141
142
/**
143
* Total body size before any truncation
144
*/
145
val bodySize: Long
146
```
147
148
**Usage Examples:**
149
150
```kotlin
151
val server = MockWebServer()
152
server.enqueue(MockResponse().setBody("OK"))
153
server.start()
154
155
// Client sends JSON data
156
val jsonData = """{"name": "John", "email": "john@example.com"}"""
157
val request = Request.Builder()
158
.url(server.url("/api/users"))
159
.post(jsonData.toRequestBody("application/json".toMediaType()))
160
.build()
161
162
client.newCall(request).execute()
163
164
// Verify request body
165
val recordedRequest = server.takeRequest()
166
assertEquals(jsonData, recordedRequest.body.readUtf8())
167
assertEquals(jsonData.length.toLong(), recordedRequest.bodySize)
168
169
// For large bodies, check truncation
170
server.bodyLimit = 100 // Limit to 100 bytes
171
// ... make request with large body ...
172
val largeRequest = server.takeRequest()
173
assertTrue(largeRequest.bodySize > 100) // Original size
174
assertTrue(largeRequest.body.size <= 100) // Truncated size
175
```
176
177
### Chunked Transfer Encoding
178
179
Information about chunked transfer encoding when used.
180
181
```kotlin { .api }
182
/**
183
* Chunk sizes if chunked transfer encoding was used
184
*/
185
val chunkSizes: List<Int>
186
```
187
188
**Usage Examples:**
189
190
```kotlin
191
// When client uses chunked encoding
192
val recordedRequest = server.takeRequest()
193
if (recordedRequest.chunkSizes.isNotEmpty()) {
194
println("Request used chunked encoding")
195
println("Chunk sizes: ${recordedRequest.chunkSizes}")
196
println("Total chunks: ${recordedRequest.chunkSizes.size}")
197
}
198
```
199
200
### Connection Metadata
201
202
Information about the connection and request sequencing.
203
204
```kotlin { .api }
205
/**
206
* Request sequence number on this connection (0-based)
207
*/
208
val sequenceNumber: Int
209
210
/**
211
* IOException if request decoding failed
212
*/
213
val failure: IOException?
214
```
215
216
**Usage Examples:**
217
218
```kotlin
219
val server = MockWebServer()
220
server.enqueue(MockResponse().setBody("Response 1"))
221
server.enqueue(MockResponse().setBody("Response 2"))
222
server.start()
223
224
// Client makes multiple requests on same connection
225
val client = OkHttpClient()
226
val request1 = Request.Builder().url(server.url("/first")).build()
227
val request2 = Request.Builder().url(server.url("/second")).build()
228
229
client.newCall(request1).execute()
230
client.newCall(request2).execute()
231
232
// Verify sequence numbers
233
val firstRequest = server.takeRequest()
234
val secondRequest = server.takeRequest()
235
236
assertEquals(0, firstRequest.sequenceNumber) // First request on connection
237
assertEquals(1, secondRequest.sequenceNumber) // Second request on same connection
238
239
// Check for decoding failures
240
assertNull(firstRequest.failure)
241
assertNull(secondRequest.failure)
242
```
243
244
### SSL/TLS Information
245
246
SSL/TLS handshake and encryption information when HTTPS is used.
247
248
```kotlin { .api }
249
/**
250
* TLS handshake information if HTTPS was used
251
*/
252
val handshake: Handshake?
253
254
/**
255
* TLS version used for HTTPS requests
256
*/
257
val tlsVersion: TlsVersion?
258
```
259
260
**Usage Examples:**
261
262
```kotlin
263
val server = MockWebServer()
264
val sslContext = SSLContext.getInstance("TLS")
265
sslContext.init(null, arrayOf(getTrustAllManager()), SecureRandom())
266
267
server.useHttps(sslContext.socketFactory, false)
268
server.enqueue(MockResponse().setBody("Secure response"))
269
server.start()
270
271
// Client makes HTTPS request
272
val request = Request.Builder()
273
.url(server.url("/secure").newBuilder().scheme("https").build())
274
.build()
275
276
client.newCall(request).execute()
277
278
// Verify SSL/TLS information
279
val recordedRequest = server.takeRequest()
280
assertNotNull(recordedRequest.handshake)
281
assertNotNull(recordedRequest.tlsVersion)
282
283
println("TLS Version: ${recordedRequest.tlsVersion}")
284
println("Cipher Suite: ${recordedRequest.handshake?.cipherSuite}")
285
println("Peer Certificates: ${recordedRequest.handshake?.peerCertificates?.size}")
286
```
287
288
### Common Verification Patterns
289
290
Typical patterns for comprehensive request verification.
291
292
**Complete Request Verification:**
293
294
```kotlin
295
fun verifyRequest(
296
recordedRequest: RecordedRequest,
297
expectedMethod: String,
298
expectedPath: String,
299
expectedHeaders: Map<String, String> = emptyMap(),
300
expectedBody: String? = null
301
) {
302
assertEquals(expectedMethod, recordedRequest.method)
303
assertEquals(expectedPath, recordedRequest.path)
304
305
expectedHeaders.forEach { (name, value) ->
306
assertEquals(value, recordedRequest.getHeader(name))
307
}
308
309
expectedBody?.let { body ->
310
assertEquals(body, recordedRequest.body.readUtf8())
311
}
312
}
313
314
// Usage
315
val recordedRequest = server.takeRequest()
316
verifyRequest(
317
recordedRequest,
318
expectedMethod = "POST",
319
expectedPath = "/api/users",
320
expectedHeaders = mapOf(
321
"Content-Type" to "application/json",
322
"Authorization" to "Bearer token123"
323
),
324
expectedBody = """{"name": "John", "email": "john@example.com"}"""
325
)
326
```
327
328
**Multiple Request Verification:**
329
330
```kotlin
331
val server = MockWebServer()
332
repeat(3) { server.enqueue(MockResponse().setBody("OK")) }
333
server.start()
334
335
// Client makes multiple requests...
336
337
// Verify all requests
338
val requests = mutableListOf<RecordedRequest>()
339
repeat(3) {
340
requests.add(server.takeRequest())
341
}
342
343
assertEquals("GET", requests[0].method)
344
assertEquals("POST", requests[1].method)
345
assertEquals("DELETE", requests[2].method)
346
347
// Verify request sequence
348
requests.forEachIndexed { index, request ->
349
assertEquals(index, request.sequenceNumber)
350
}
351
```