0
# Interceptors
1
2
Pluggable request and response transformation framework for monitoring, rewriting, and retry logic.
3
4
## Interceptor Interface
5
6
```kotlin { .api }
7
interface Interceptor {
8
fun intercept(chain: Chain): Response
9
10
interface Chain {
11
fun request(): Request
12
fun proceed(request: Request): Response
13
fun connection(): Connection?
14
fun call(): Call
15
fun connectTimeoutMillis(): Int
16
fun withConnectTimeout(timeout: Int, unit: TimeUnit): Chain
17
fun readTimeoutMillis(): Int
18
fun withReadTimeout(timeout: Int, unit: TimeUnit): Chain
19
fun writeTimeoutMillis(): Int
20
fun withWriteTimeout(timeout: Int, unit: TimeUnit): Chain
21
}
22
}
23
```
24
25
## Application vs Network Interceptors
26
27
- **Application Interceptors**: Called once per request, see final redirected response
28
- **Network Interceptors**: Called for each network request, including redirects and retries
29
30
```kotlin
31
val client = OkHttpClient.Builder()
32
.addInterceptor(applicationInterceptor) // Application-level
33
.addNetworkInterceptor(networkInterceptor) // Network-level
34
.build()
35
```
36
37
## Common Interceptor Patterns
38
39
### Logging Interceptor
40
41
```kotlin
42
class LoggingInterceptor : Interceptor {
43
override fun intercept(chain: Interceptor.Chain): Response {
44
val request = chain.request()
45
46
val t1 = System.nanoTime()
47
println("Sending request ${request.url}")
48
49
val response = chain.proceed(request)
50
51
val t2 = System.nanoTime()
52
println("Received response for ${response.request.url} in ${(t2 - t1) / 1e6} ms")
53
54
return response
55
}
56
}
57
```
58
59
### Authentication Interceptor
60
61
```kotlin
62
class AuthInterceptor(private val token: String) : Interceptor {
63
override fun intercept(chain: Interceptor.Chain): Response {
64
val request = chain.request().newBuilder()
65
.addHeader("Authorization", "Bearer $token")
66
.build()
67
return chain.proceed(request)
68
}
69
}
70
```
71
72
### Retry Interceptor
73
74
```kotlin
75
class RetryInterceptor(private val maxRetries: Int = 3) : Interceptor {
76
override fun intercept(chain: Interceptor.Chain): Response {
77
var request = chain.request()
78
var response = chain.proceed(request)
79
var retryCount = 0
80
81
while (!response.isSuccessful && retryCount < maxRetries) {
82
retryCount++
83
response.close()
84
response = chain.proceed(request)
85
}
86
87
return response
88
}
89
}
90
```
91
92
### Cache Override Interceptor
93
94
```kotlin
95
class CacheInterceptor : Interceptor {
96
override fun intercept(chain: Interceptor.Chain): Response {
97
val request = chain.request()
98
99
// Modify request based on network availability
100
val cacheControl = if (isNetworkAvailable()) {
101
CacheControl.Builder()
102
.maxAge(5, TimeUnit.MINUTES)
103
.build()
104
} else {
105
CacheControl.Builder()
106
.onlyIfCached()
107
.maxStale(7, TimeUnit.DAYS)
108
.build()
109
}
110
111
val cacheRequest = request.newBuilder()
112
.cacheControl(cacheControl)
113
.build()
114
115
return chain.proceed(cacheRequest)
116
}
117
}
118
```