PathHandler.kt

  1. package com.hexagontk.http.handlers

  2. import com.hexagontk.core.media.TEXT_PLAIN
  3. import com.hexagontk.core.toText
  4. import com.hexagontk.handlers.ChainHandler
  5. import com.hexagontk.handlers.Handler
  6. import com.hexagontk.http.model.*
  7. import com.hexagontk.http.model.HttpMethod.Companion.ALL

  8. class PathHandler(
  9.     override val handlerPredicate: HttpPredicate,
  10.     val handlers: List<HttpHandler>,
  11. ) :
  12.     HttpHandler,
  13.     Handler<HttpCall> by ChainHandler(
  14.         handlers.map { it.addPrefix(handlerPredicate.pathPattern.pattern) },
  15.         handlerPredicate,
  16.     )
  17. {

  18.     private companion object {
  19.         fun nestedMethods(handlers: List<HttpHandler>): Set<HttpMethod> =
  20.             handlers
  21.                 .flatMap { it.handlerPredicate.methods.ifEmpty { ALL } }
  22.                 .toSet()
  23.     }

  24.     constructor(vararg handlers: HttpHandler) :
  25.         this(
  26.             HttpPredicate(methods = nestedMethods(handlers.toList())),
  27.             handlers.toList()
  28.         )

  29.     constructor(pattern: String, handlers: List<HttpHandler>) :
  30.         this(
  31.             HttpPredicate(
  32.                 methods = nestedMethods(handlers.toList()),
  33.                 pattern = pattern,
  34.                 prefix = true,
  35.             ),
  36.             handlers
  37.         )

  38.     constructor(pattern: String, vararg handlers: HttpHandler) :
  39.         this(pattern, handlers.toList())

  40.     override fun process(request: HttpRequestPort): HttpContext =
  41.         process(HttpContext(HttpCall(request = request), predicate)).let {
  42.             val event = it.event
  43.             val response = event.response
  44.             val exception = it.exception

  45.             if (exception != null) {
  46.                 if (response.status !in SERVER_ERROR)
  47.                     it.with(
  48.                         event = HttpCall(
  49.                             event.request,
  50.                             response.with(
  51.                                 body = exception.toText(),
  52.                                 contentType = ContentType(TEXT_PLAIN),
  53.                                 status = INTERNAL_SERVER_ERROR_500,
  54.                             )
  55.                         )
  56.                     )
  57.                 else
  58.                     it
  59.             }
  60.             else {
  61.                 it
  62.             }
  63.         } as HttpContext

  64.     override fun addPrefix(prefix: String): HttpHandler =
  65.         PathHandler(handlerPredicate.addPrefix(prefix), handlers)

  66.     fun describe(): String =
  67.         listOf(
  68.             listOf(handlerPredicate.describe()),
  69.             handlers
  70.                 .map {
  71.                     when (it) {
  72.                         is PathHandler -> it.describe()
  73.                         else -> it.handlerPredicate.describe()
  74.                     }
  75.                 }
  76.                 .map {it.prependIndent(" ".repeat(4)) }
  77.         )
  78.         .flatten()
  79.         .joinToString("\n") { it }
  80. }