HelidonRequestAdapter.kt

  1. package com.hexagontk.http.server.helidon

  2. import com.hexagontk.core.media.MediaType
  3. import com.hexagontk.core.media.MediaTypeGroup
  4. import com.hexagontk.http.model.*
  5. import com.hexagontk.http.patterns.PathPattern
  6. import io.helidon.http.HeaderNames
  7. import io.helidon.http.Method
  8. import io.helidon.http.media.multipart.MultiPart
  9. import io.helidon.webserver.http.ServerRequest
  10. import java.security.cert.X509Certificate
  11. import kotlin.jvm.optionals.getOrNull

  12. class HelidonRequestAdapter(
  13.     methodName: Method,
  14.     req: ServerRequest,
  15. ) : HttpRequestPort {

  16.     override val certificateChain: List<X509Certificate> by lazy {
  17.         req.remotePeer().tlsCertificates().getOrNull()
  18.             ?.toList()
  19.             ?.map { it as X509Certificate }
  20.             ?: emptyList()
  21.     }

  22.     override val accept: List<ContentType> by lazy {
  23.         req.headers().acceptedTypes().map {
  24.             val mt = it.mediaType()
  25.             val t = mt.type().uppercase()
  26.             val st = mt.subtype()
  27.             ContentType(MediaType(MediaTypeGroup.valueOf(t), st))
  28.         }
  29.     }

  30.     override val contentLength: Long by lazy {
  31.         req.headers().get(HeaderNames.CONTENT_LENGTH).get().toLong()
  32.     }

  33.     override val queryParameters: Parameters by lazy {
  34.         Parameters(
  35.             req.query().names().flatMap { n ->
  36.                 val all = req.query().all(n)
  37.                 if (all.isEmpty()) listOf(Parameter(n))
  38.                 else all.map { Parameter(n, it) }
  39.             }
  40.         )
  41.     }

  42.     override val parts: List<HttpPart> by lazy {
  43.         try {
  44.             val multiPart = req.content().`as`(MultiPart::class.java)
  45.             var parts = emptyList<HttpPart>()
  46.             // TODO Fails when parsing multiple parts !?
  47.             multiPart.forEach { p ->
  48.                 val name = p.name()
  49.                 val bytes = p.inputStream().readAllBytes()
  50.                 val fileName = p.fileName().getOrNull()
  51.                     ?.let { HttpPart(name, bytes, it) }
  52.                     ?: HttpPart(name, String(bytes))

  53.                 parts = parts + fileName
  54.             }
  55.             parts
  56.         }
  57.         catch (e: Exception) {
  58.             emptyList()
  59.         }
  60.     }

  61.     override val formParameters: Parameters by lazy {
  62.         val fields = parts
  63.             .filter { it.submittedFileName == null }
  64.             .map { Parameter(it.name, it.bodyString()) }

  65.         Parameters(fields)
  66.     }

  67.     override val method: HttpMethod by lazy {
  68.         HttpMethod.valueOf(methodName.text())
  69.     }

  70.     override val protocol: HttpProtocol by lazy {
  71.         HttpProtocol.valueOf(req.prologue().protocol())
  72.     }

  73.     override val host: String by lazy {
  74.         req.remotePeer().host()
  75.     }

  76.     override val port: Int by lazy {
  77.         req.remotePeer().port()
  78.     }

  79.     override val path: String by lazy {
  80.         req.path().path()
  81.     }

  82.     override val cookies: List<Cookie> by lazy {
  83.         req.headers().cookies().toMap().map { (k, v) -> Cookie(k, v.first()) }
  84.     }

  85.     override val body: Any by lazy {
  86.         req.content().inputStream().readAllBytes()
  87.     }

  88.     override val headers: Headers by lazy {
  89.         Headers(
  90.             req.headers().flatMap { h -> h.allValues().map { Header(h.name(), it) } }
  91.         )
  92.     }

  93.     override val contentType: ContentType? by lazy {
  94.         req.headers().contentType().map {
  95.             val mt = it.mediaType()
  96.             val t = mt.type().uppercase()
  97.             val st = mt.subtype()
  98.             ContentType(MediaType(MediaTypeGroup.valueOf(t), st))
  99.         }
  100.         .orElse(null)
  101.     }

  102.     override val authorization: Authorization? by lazy { authorization() }

  103.     override val pathPattern: PathPattern? = null

  104.     override val pathParameters: Map<String, Any> by lazy { throw UnsupportedOperationException() }

  105.     override fun with(
  106.         body: Any,
  107.         headers: Headers,
  108.         contentType: ContentType?,
  109.         method: HttpMethod,
  110.         protocol: HttpProtocol,
  111.         host: String,
  112.         port: Int,
  113.         path: String,
  114.         queryParameters: Parameters,
  115.         parts: List<HttpPart>,
  116.         formParameters: Parameters,
  117.         cookies: List<Cookie>,
  118.         accept: List<ContentType>,
  119.         authorization: Authorization?,
  120.         certificateChain: List<X509Certificate>,
  121.         pathPattern: PathPattern?,
  122.         pathParameters: Map<String, Any>,
  123.     ): HttpRequestPort =
  124.         throw UnsupportedOperationException()
  125. }