@@ -7,7 +7,9 @@ import mockwebserver3.MockWebServer
77import mockwebserver3.RecordedRequest
88import okhttp3.WebSocket
99import okhttp3.WebSocketListener
10+ import okio.Buffer
1011import okio.ByteString
12+ import okio.ByteString.Companion.decodeBase64
1113import java.net.InetAddress
1214import java.util.concurrent.TimeUnit
1315
@@ -39,6 +41,7 @@ private fun createServer(): MockWebServer {
3941 val postBody = """ {"ok":true,"endpoint":"post","source":"mockwebserver"}"""
4042 val gzipPostBody = """ {"ok":true,"endpoint":"post-gzip-unknown-length","source":"mockwebserver"}"""
4143 val noTypeBody = """ {"message":"Hello from Snap-O without Content-Type","source":"okhttp-demo"}"""
44+ val imageBody = checkNotNull(DemoAppIconPng .decodeBase64())
4245 val formBody = """ {"ok":true,"endpoint":"form-post","source":"mockwebserver"}"""
4346 val slowBody = """ {"message":"${" x" .repeat(SlowBodyPayloadCharacters )} ","source":"okhttp-demo"}"""
4447 return MockWebServer ().apply {
@@ -80,6 +83,7 @@ private fun createServer(): MockWebServer {
8083 .setHeader(" Connection" , " close" )
8184 .body(noTypeBody)
8285 .build()
86+ " /image.png" -> imageResponse(imageBody)
8387 " /slow-response" -> slowResponse(slowBody)
8488 " /ws-echo" -> MockResponse .Builder ()
8589 .webSocketUpgrade(
@@ -103,6 +107,13 @@ private fun createServer(): MockWebServer {
103107 }
104108}
105109
110+ private fun imageResponse (body : ByteString ): MockResponse = MockResponse .Builder ()
111+ .code(200 )
112+ .setHeader(" Content-Type" , " image/png" )
113+ .setHeader(" Connection" , " close" )
114+ .body(Buffer ().write(body))
115+ .build()
116+
106117private fun slowResponse (body : String ): MockResponse = MockResponse .Builder ()
107118 .code(200 )
108119 .setHeader(" Content-Type" , " application/json; charset=utf-8" )
@@ -131,3 +142,65 @@ private const val SlowBodyPayloadCharacters: Int = 1024 * 1024
131142private const val SlowBodyInitialDelayMs : Long = 2_000L
132143private const val SlowBodyChunkBytes : Long = 128L * 1024L
133144private const val SlowBodyChunkDelayMs : Long = 250L
145+
146+ private val DemoAppIconPng : String = """
147+ iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAHsUExURUdwTJDci5/jm1vOVDnJMTfHLjvI
148+ M6zyp0nPQH3idz/MNzvKMj7MNjjIL0HNOJ/umqTvn3nfclPTTDjJMLj2tHffcT3LNTzJM3nfc3TcboTjfoPjfkjPQF7WVnvidYLkfIflg7j3tXrfdJfqknTc
149+ bXDca5frkrr4t6fxo6fwoyO1GyS0HCS0GSa1GyW2GyO1Gf///yGzGSG0GiCyFyCxFyG2Gx2wFUXGPfn/9/b+9Su8IvP+8v7//bzoufH88Mzvyfr/+q/krByu
150+ FMDpvfb/9bfnteP44W/aaSq7Iim4Ief/5Nn/1u797sjuxjTELLTksTPFK83xy8DsvnPPbbvruMTtwcTrw+T641vFVZfek9Pz0eL/3uf75dj019v12vT989/5
151+ 3tL/z1LCTOz/6MfwxS6/JSOvG+D33u//7Pv//CWzHG7badDwzev76/P/7sT2wdHxz0y+RSm1ITDCKLLmrk7LRsj7xVPOTOr86bbxs0O9O2XJX23MZzG2KH3T
152+ eNXx1De2L4rYhdb31Of45zy5Nc/8zHjRcrXssr31ukjIQCuzI/3/9iaxHj3DNTO7K6XmoXfccGfWYTO+K67uqsr/xqrlpxysE8Dwvcz3yYHVfK3pqVzSVRmt
153+ Ex+uF4njg9f91YXXf4XWgEfLPxurE6OFYTUAAAAqdFJOUwD+/vfB8f5kiWBoo2DfNIzM1h0FoOxZ0uH0o8ETtjQTBQX0tr/FNjIdHUb5dt8AABHjSURBVHja
154+ 7Fj7c9vGEY5Uu46TurbrOHWdtpkknSTlHYgD+DBNcjIaDksLIMfTGXqGYEjKFBFTlDyShlRo0XyopCzJelBvy3rZkt3+o907ABRBSaCk/KodEQJwuNtvH7e3
155+ u598ckmXdEmXdEmX1I2+/v76zftf3b5399s1oOePHj16/ohe9Qt7eK6/Mugvd+/d/sf9T6///evfyPyf177rWVtbX9+fnJwsFosLCwsPzkDwWXGhWIQ5k/u/
156+ +9tnf7oo92+u3TpYW59cWN6QJLtNI6RdMLsi4yXibMfHOUla2VhefvD7/1758s5F+AP79eKyBEsy7vSC2T/Gzc7r7LqN2/s3Jh7f+MO52f8A7BeAO12Xp0vx
157+ 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
205+ QmCC
206+ """ .trimIndent()
0 commit comments