-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathBody.kt
54 lines (45 loc) · 2.17 KB
/
Body.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package klite
import java.io.InputStream
import java.io.OutputStream
import kotlin.reflect.KClass
import kotlin.reflect.KType
interface SupportsContentType {
val contentType: String
}
class Accept(val contentTypes: String?) {
val isRelaxed get() = contentTypes == null || contentTypes.contains("*") || contentTypes.startsWith("text/html,")
operator fun invoke(contentType: String) = contentTypes?.contains(contentType) ?: true
operator fun invoke(provider: SupportsContentType) = invoke(provider.contentType)
}
interface BodyRenderer: SupportsContentType {
fun render(output: OutputStream, value: Any?) { throw UnsupportedOperationException() }
fun render(e: HttpExchange, code: StatusCode, value: Any?) {
e.startResponse(code, contentType = contentType).use { render(it, value) }
}
}
interface BodyParser: SupportsContentType {
@Deprecated("Use/implement the KType method")
fun <T: Any> parse(input: InputStream, type: KClass<T>): T = throw UnsupportedOperationException()
@Suppress("UNCHECKED_CAST")
fun <T: Any> parse(input: InputStream, type: KType): T = parse(input, type.classifier as KClass<T>)
fun <T> parse(e: HttpExchange, type: KType): T = e.requestStream.use { parse(it, type) }
}
class TextBodyRenderer(override val contentType: String = MimeTypes.text): BodyRenderer {
override fun render(output: OutputStream, value: Any?) = output.write(value.toString())
}
class TextBodyParser(override val contentType: String = MimeTypes.text): BodyParser {
@Suppress("UNCHECKED_CAST")
override fun <T: Any> parse(input: InputStream, type: KType): T {
val s = input.reader().readText()
return if (type == String::class) s as T else Converter.from(s, type)
}
}
class TextBody(
override val contentType: String = MimeTypes.text,
private val renderer: TextBodyRenderer = TextBodyRenderer(contentType),
private val parser: TextBodyParser = TextBodyParser(contentType)
): BodyRenderer by renderer, BodyParser by parser
class FormUrlEncodedParser(override val contentType: String = MimeTypes.wwwForm): BodyParser {
@Suppress("UNCHECKED_CAST")
override fun <T : Any> parse(input: InputStream, type: KType): T = urlDecodeParams(input.reader().readText()) as T
}