添加各种映射

This commit is contained in:
tursom 2019-11-30 15:05:18 +08:00
parent fbabf71a3b
commit a775ba1b5e
17 changed files with 162 additions and 25 deletions

View File

@ -119,8 +119,6 @@ interface HttpContent : ResponseHeaderAdapter, RequestHeaderAdapter {
chunkSize: Int = 8192
)
fun setContextType(type: Any) = setResponseHeader("Content-Type", type)
fun jump(url: String) = temporaryMoved(url)
fun moved(url: String) = permanentlyMoved(url)

View File

@ -1,6 +1,7 @@
package cn.tursom.web
import cn.tursom.web.utils.CacheControl
import cn.tursom.web.utils.ContextTypeMap
import cn.tursom.web.utils.Cookie
import cn.tursom.web.utils.SameSite
@ -53,7 +54,11 @@ interface ResponseHeaderAdapter {
fun range(start: Int, end: Int, resourceSize: Int) = setResponseHeader("Content-Range", "$start-$end/$resourceSize")
fun range(resourceSize: Int) = setResponseHeader("Content-Range", "*/$resourceSize")
fun setContextType(type: Any) = setResponseHeader("Content-Type", type)
fun responseHtml() = setResponseHeader("content-type", "text/html; charset=UTF-8")
fun responseText() = setResponseHeader("content-type", "text/plain; charset=UTF-8")
fun responseJson() = setResponseHeader("content-type", "application/json; charset=UTF-8")
fun autoContextType(type: String) = setContextType(ContextTypeMap[type] ?: "application/octet-stream")
}

View File

@ -1,4 +1,4 @@
package cn.tursom.web.router.mapping
package cn.tursom.web.mapping
annotation class ConnectMapping(
vararg val route: String

View File

@ -1,4 +1,4 @@
package cn.tursom.web.router.mapping
package cn.tursom.web.mapping
annotation class DeleteMapping(
vararg val route: String

View File

@ -1,4 +1,4 @@
package cn.tursom.web.router.mapping
package cn.tursom.web.mapping
annotation class GetMapping(
vararg val route: String

View File

@ -1,4 +1,4 @@
package cn.tursom.web.router.mapping
package cn.tursom.web.mapping
annotation class HeadMapping(
vararg val route: String

View File

@ -1,4 +1,4 @@
package cn.tursom.web.router.mapping
package cn.tursom.web.mapping
annotation class Mapping(
vararg val route: String,

View File

@ -1,4 +1,4 @@
package cn.tursom.web.router.mapping
package cn.tursom.web.mapping
annotation class OptionsMapping(
vararg val route: String

View File

@ -1,4 +1,4 @@
package cn.tursom.web.router.mapping
package cn.tursom.web.mapping
annotation class PatchMapping(
vararg val route: String

View File

@ -1,4 +1,4 @@
package cn.tursom.web.router.mapping
package cn.tursom.web.mapping
annotation class PostMapping(
vararg val route: String

View File

@ -1,4 +1,4 @@
package cn.tursom.web.router.mapping
package cn.tursom.web.mapping
annotation class PutMapping(
vararg val route: String

View File

@ -1,4 +1,4 @@
package cn.tursom.web.router.mapping
package cn.tursom.web.mapping
annotation class TraceMapping(
vararg val route: String

View File

@ -0,0 +1,3 @@
package cn.tursom.web.result
annotation class Html

View File

@ -0,0 +1,3 @@
package cn.tursom.web.result
annotation class Json

View File

@ -0,0 +1,3 @@
package cn.tursom.web.result
annotation class Text

View File

@ -1,11 +1,15 @@
package cn.tursom.web.router
import cn.tursom.core.buffer.ByteBuffer
import cn.tursom.json.JsonWorkerImpl
import cn.tursom.web.ExceptionContent
import cn.tursom.web.HttpContent
import cn.tursom.web.HttpHandler
import cn.tursom.web.router.impl.SimpleRouter
import cn.tursom.web.router.mapping.*
import cn.tursom.web.mapping.*
import cn.tursom.web.result.Html
import cn.tursom.web.result.Json
import cn.tursom.web.result.Text
import cn.tursom.web.utils.Chunked
import org.slf4j.LoggerFactory
import java.io.File
@ -50,10 +54,9 @@ open class RoutedHttpHandler<T : HttpContent, in E : ExceptionContent>(
@Suppress("LeakingThis")
val clazz = handler.javaClass
clazz.methods.forEach { method ->
log?.debug("try mapping {}", method)
method.parameterTypes.let {
if (it.size != 1 || !HttpContent::class.java.isAssignableFrom(it[0])) {
return@forEach
} else if (it.isNotEmpty()) {
if (!(it.size == 1 && HttpContent::class.java.isAssignableFrom(it[0])) && it.isNotEmpty()) {
return@forEach
}
}
@ -128,15 +131,11 @@ open class RoutedHttpHandler<T : HttpContent, in E : ExceptionContent>(
router[safeRoute(route)] = handler@{ content ->
if (method.parameterTypes.isEmpty()) {
val result = method(obj) ?: return@handler
when (result) {
is String -> content.finishHtml(result.toByteArray())
is ByteArray -> content.finishText(result)
is File -> content.finishFile(result)
is RandomAccessFile -> content.finishFile(result)
is Chunked -> content.finishChunked(result)
else -> json?.let {
content.finishJson(json.toJson(result)!!.toByteArray())
} ?: content.finishText(result.toString().toByteArray())
when {
method.getAnnotation(Html::class.java) != null -> finishHtml(result, content)
method.getAnnotation(Text::class.java) != null -> finishText(result, content)
method.getAnnotation(Json::class.java) != null -> finishJson(result, content)
else -> autoReturn(result, content)
}
} else {
method(obj, content)
@ -173,5 +172,48 @@ open class RoutedHttpHandler<T : HttpContent, in E : ExceptionContent>(
}
private fun safeRoute(route: String) = if (route.first() == '/') route else "/$route"
private fun autoReturn(result: Any, content: HttpContent) = when (result) {
is String -> content.finishText(result.toByteArray())
is ByteArray -> content.finishText(result)
is File -> {
content.autoContextType(result.name)
content.finishFile(result)
}
is RandomAccessFile -> content.finishFile(result)
is Chunked -> content.finishChunked(result)
else -> finishJson(result, content)
}
private fun finishHtml(result: Any, content: HttpContent) = when (result) {
is ByteBuffer -> content.finishHtml(result)
is ByteArray -> content.finishHtml(result)
is String -> content.finishHtml(result.toByteArray())
else -> content.finishHtml(result.toString().toByteArray())
}
private fun finishText(result: Any, content: HttpContent) = when (result) {
is ByteBuffer -> content.finishText(result)
is ByteArray -> content.finishText(result)
is String -> content.finishText(result.toByteArray())
else -> content.finishText(result.toString().toByteArray())
}
private fun finishJson(result: Any, content: HttpContent) {
when (result) {
is ByteBuffer -> content.finishJson(result)
is ByteArray -> content.finishJson(result)
is String -> content.finishJson("\"$result\"".toByteArray())
is Byte, Short, Int, Long, Float, Double, Boolean -> content.finishJson(result.toString().toByteArray())
else -> {
val json = json?.toJson(result)?.toByteArray()
if (json != null) {
content.finishJson(json)
} else {
content.finishText(result.toString().toByteArray())
}
}
}
}
}
}

View File

@ -0,0 +1,83 @@
package cn.tursom.web.utils
import cn.tursom.core.datastruct.StringRadixTree
object ContextTypeMap {
private val router = StringRadixTree<String>()
operator fun get(type: String) = router[type.substringAfterLast('.')]
init {
router["aac"] = "audio/aac"
router["abw"] = "application/x-abiword"
router["arc"] = "application/x-freearc"
router["avi"] = "video/x-msvideo"
router["azw"] = "aapplication/vnd.amazon.ebook"
router["bin"] = "application/octet-stream"
router["bmp"] = "image/bmp"
router["bz"] = "application/x-bzip"
router["bz2"] = "application/x-bzip2"
router["csh"] = "application/x-csh"
router["css"] = "itext/css; charset=UTF-8"
router["csv"] = "itext/csv; charset=UTF-8"
router["doc"] = "application/msword"
router["docx"] = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
router["eot"] = "application/vnd.ms-fontobject"
router["epub"] = "application/epub+zip"
router["gif"] = "image/gif"
router["html"] = "text/html; charset=UTF-8"
router["htm"] = "text/html; charset=UTF-8"
router["ico"] = "image/vnd.microsoft.icon"
router["ics"] = "text/calendar; charset=UTF-8"
router["jar"] = "application/java-archive"
router["jpeg"] = "image/jpeg"
router["jpg"] = "image/jpeg"
router["js"] = "text/javascript; charset=UTF-8"
router["json"] = "application/json; charset=UTF-8"
router["jsonld"] = "application/ld+json"
router["mid"] = "audio/midi"
router["midi"] = "audio/midi"
router["mjs"] = "text/javascript"
router["mp3"] = "audio/mpeg"
router["mp4"] = "audio/mp4"
router["mpeg"] = "video/mpeg"
router["mpkg"] = "application/vnd.apple.installer+xml"
router["odp"] = "application/vnd.oasis.opendocument.presentation"
router["ods"] = "application/vnd.oasis.opendocument.spreadsheet"
router["odt"] = "application/vnd.oasis.opendocument.text"
router["oga"] = "audio/ogg"
router["ogg"] = "application/ogg"
router["ogv"] = "video/ogg"
router["ogx"] = "application/ogg"
router["otf"] = "font/otf"
router["png"] = "image/png"
router["pdf"] = "application/pdf"
router["ppt"] = "application/vnd.ms-powerpoint"
router["pptx"] = "application/vnd.openxmlformats-officedocument.presentationml.presentation"
router["rar"] = "application/x-rar-compressed"
router["rtf"] = "application/rtf"
router["sh"] = "application/x-sh"
router["svg"] = "image/svg+xml"
router["swf"] = "application/x-shockwave-flash"
router["tar"] = "application/x-tar"
router["tif"] = "image/tiff"
router["tiff"] = "image/tiff"
router["ttf"] = "font/ttf"
router["txt"] = "text/plain; charset=UTF-8"
router["vsd"] = "application/vnd.visio"
router["wav"] = "audio/wav"
router["weba"] = "audio/webm"
router["webm"] = "video/webm"
router["webp"] = "image/webp"
router["woff"] = "font/woff"
router["woff2"] = "font/woff2"
router["xhtml"] = "application/xhtml+xml"
router["xls"] = "application/vnd.ms-excel"
router["xlsx"] = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
router["xml"] = "text/xml; charset=UTF-8"
router["xul"] = "application/vnd.mozilla.xul+xml"
router["zip"] = "application/zip"
router["3gp"] = "video/3gpp"
router["3g2"] = "ivideo/3gpp2"
router["7z"] = "application/x-7z-compressed"
}
}