NettyRequestAdapter.kt
- package com.hexagontk.http.server.netty
- import com.hexagontk.http.model.*
- import com.hexagontk.http.parseContentType
- import com.hexagontk.http.patterns.PathPattern
- import io.netty.buffer.ByteBufHolder
- import io.netty.buffer.ByteBufUtil
- import io.netty.buffer.Unpooled
- import io.netty.channel.Channel
- import io.netty.handler.codec.http.HttpHeaderNames.*
- import io.netty.handler.codec.http.HttpHeaders
- import io.netty.handler.codec.http.QueryStringDecoder
- import io.netty.handler.codec.http.cookie.Cookie
- import io.netty.handler.codec.http.cookie.ServerCookieDecoder
- import io.netty.handler.codec.http.multipart.*
- import io.netty.handler.codec.http.HttpRequest
- import io.netty.handler.codec.http.cookie.CookieHeaderNames.SameSite.*
- import io.netty.handler.codec.http.cookie.DefaultCookie
- import java.net.InetSocketAddress
- import java.net.URI
- import java.security.cert.X509Certificate
- import kotlin.Long.Companion.MIN_VALUE
- import io.netty.handler.codec.http.HttpMethod as NettyHttpMethod
- class NettyRequestAdapter(
- methodName: NettyHttpMethod,
- req: HttpRequest,
- override val certificateChain: List<X509Certificate>,
- channel: Channel,
- nettyHeaders: HttpHeaders,
- ) : HttpRequestPort {
- private val address: InetSocketAddress by lazy { channel.remoteAddress() as InetSocketAddress }
- override val accept: List<ContentType> by lazy {
- nettyHeaders.getAll(ACCEPT).flatMap { it.split(",") }.map { parseContentType(it) }
- }
- override val contentLength: Long by lazy {
- nettyHeaders[CONTENT_LENGTH]?.toLong() ?: 0L
- }
- override val queryParameters: Parameters by lazy {
- val queryStringDecoder = QueryStringDecoder(req.uri())
- Parameters(
- queryStringDecoder.parameters().flatMap { (k, v) -> v.map { Parameter(k, it) } }
- )
- }
- override val parts: List<HttpPart> by lazy {
- HttpPostRequestDecoder(req).bodyHttpDatas.map {
- when (it) {
- is FileUpload -> HttpPart(
- name = it.name,
- body = ByteBufUtil.getBytes(it.content()),
- submittedFileName = it.filename,
- contentType = it.contentType?.let { ct -> parseContentType(ct) },
- )
- is Attribute -> HttpPart(it.name, it.value)
- else -> error("Unknown part type: ${it.javaClass}")
- }
- }
- }
- override val formParameters: Parameters by lazy {
- val fields = parts
- .filter { it.submittedFileName == null }
- .map { Parameter(it.name, it.bodyString()) }
- Parameters(fields)
- }
- override val method: HttpMethod by lazy {
- HttpMethod.valueOf(methodName.name())
- }
- override val protocol: HttpProtocol by lazy {
- HttpProtocol.valueOf(req.protocolVersion().protocolName())
- }
- override val host: String by lazy {
- address.hostName
- }
- override val port: Int by lazy {
- address.port
- }
- override val path: String by lazy { URI(req.uri()).path }
- override val cookies: List<com.hexagontk.http.model.Cookie> by lazy {
- val cookieHeader: String = nettyHeaders.get(COOKIE)
- ?: return@lazy emptyList<com.hexagontk.http.model.Cookie>()
- val cookies: Set<Cookie> = ServerCookieDecoder.STRICT.decode(cookieHeader)
- cookies.map {
- Cookie(
- name = it.name(),
- value = it.value(),
- maxAge = if (it.maxAge() == MIN_VALUE) -1 else it.maxAge(),
- secure = it.isSecure,
- path = it.path() ?: "/",
- httpOnly = it.isHttpOnly,
- sameSite = (it as? DefaultCookie)?.sameSite()?.let { ss ->
- when (ss) {
- Strict -> CookieSameSite.STRICT
- Lax -> CookieSameSite.LAX
- None -> CookieSameSite.NONE
- }
- },
- domain = it.domain(),
- )
- }
- }
- override val body: Any by lazy {
- val content =
- if (req is ByteBufHolder) req.content()
- else Unpooled.buffer(0)
- if (content.isReadable) ByteBufUtil.getBytes(content)
- else byteArrayOf()
- }
- override val headers: Headers by lazy {
- Headers(
- nettyHeaders.names()
- .toList()
- .map { it.lowercase() }
- .flatMap { h -> nettyHeaders.getAll(h).map { Header(h, it) } }
- )
- }
- override val contentType: ContentType? by lazy {
- nettyHeaders[CONTENT_TYPE]?.let { parseContentType(it) }
- }
- override val authorization: Authorization? by lazy { authorization() }
- override val pathPattern: PathPattern? = null
- override val pathParameters: Map<String, Any> by lazy { throw UnsupportedOperationException() }
- override fun with(
- body: Any,
- headers: Headers,
- contentType: ContentType?,
- method: HttpMethod,
- protocol: HttpProtocol,
- host: String,
- port: Int,
- path: String,
- queryParameters: Parameters,
- parts: List<HttpPart>,
- formParameters: Parameters,
- cookies: List<com.hexagontk.http.model.Cookie>,
- accept: List<ContentType>,
- authorization: Authorization?,
- certificateChain: List<X509Certificate>,
- pathPattern: PathPattern?,
- pathParameters: Map<String, Any>,
- ): HttpRequestPort =
- throw UnsupportedOperationException()
- }