Created
May 24, 2021 16:02
-
-
Save yusukezzz/5ad8011297d85e3580fdae87bf447e16 to your computer and use it in GitHub Desktop.
Jte feature for ktor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package net.yusukezzz | |
import gg.jte.CodeResolver | |
import gg.jte.TemplateEngine | |
import gg.jte.output.WriterOutput | |
import gg.jte.resolve.DirectoryCodeResolver | |
import io.ktor.application.* | |
import io.ktor.http.* | |
import io.ktor.http.content.* | |
import io.ktor.response.* | |
import io.ktor.util.* | |
import io.ktor.util.cio.* | |
import io.ktor.utils.io.* | |
import java.nio.file.* | |
import gg.jte.ContentType as JteContentType | |
class JteContent( | |
val template: String, | |
val data: Any?, | |
val contentType: ContentType = ContentType.Text.Html.withCharset(Charsets.UTF_8) | |
) | |
suspend fun ApplicationCall.respondTemplate( | |
template: String, | |
data: Any? = null, | |
contentType: ContentType = ContentType.Text.Html.withCharset(Charsets.UTF_8) | |
): Unit = respond(JteContent(template, data, contentType)) | |
class Jte(config: Configuration) { | |
private val extention: String = ".jte" | |
private val engine: TemplateEngine = | |
TemplateEngine.create(config.resolver, config.contentType) | |
class Configuration { | |
var resolver: CodeResolver = | |
DirectoryCodeResolver(Paths.get(ClassLoader.getSystemResource("jte").toURI())) | |
var contentType: JteContentType = JteContentType.Html | |
} | |
companion object Feature : ApplicationFeature<ApplicationCallPipeline, Configuration, Jte> { | |
override val key: AttributeKey<Jte> = AttributeKey<Jte>("Jte") | |
override fun install(pipeline: ApplicationCallPipeline, configure: Configuration.() -> Unit): Jte { | |
val configuration = Configuration().apply(configure) | |
val feature = Jte(configuration) | |
pipeline.sendPipeline.intercept(ApplicationSendPipeline.Transform) { value -> | |
if (value is JteContent) { | |
val response = feature.process(value) | |
proceedWith(response) | |
} | |
} | |
return feature | |
} | |
} | |
private fun process(content: JteContent): JteOutgoingContent { | |
return JteOutgoingContent( | |
engine, | |
resolveExtension(content.template), | |
content.data, | |
content.contentType | |
) | |
} | |
private fun resolveExtension(template: String): String { | |
return if (template.endsWith(extention)) { | |
template | |
} else { | |
template + extention | |
} | |
} | |
private class JteOutgoingContent( | |
val engine: TemplateEngine, | |
val template: String, | |
val data: Any?, | |
override val contentType: ContentType | |
) : OutgoingContent.WriteChannelContent() { | |
override suspend fun writeTo(channel: ByteWriteChannel) { | |
channel.bufferedWriter(contentType.charset() ?: Charsets.UTF_8).use { | |
engine.render(template, data, WriterOutput(it)) | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment