GoogleHttpFunction.kt

  1. package com.hexagontk.serverless.http.google

  2. import com.hexagontk.http.handlers.bodyToBytes
  3. import com.google.cloud.functions.HttpFunction
  4. import com.google.cloud.functions.HttpRequest
  5. import com.google.cloud.functions.HttpResponse
  6. import com.hexagontk.core.media.TEXT_PLAIN
  7. import com.hexagontk.core.toText
  8. import com.hexagontk.http.handlers.HttpContext
  9. import com.hexagontk.http.handlers.HttpHandler
  10. import com.hexagontk.http.model.*
  11. import com.hexagontk.http.parseContentType
  12. import java.net.URI

  13. class GoogleHttpFunction(private val handler: HttpHandler): HttpFunction {

  14.     override fun service(request: HttpRequest, response: HttpResponse) {
  15.         val handlerRequest = createRequest(request)
  16.         val handlerContext = handler.process(handlerRequest)
  17.         writeResponse(response, handlerContext)
  18.     }

  19.     private fun createRequest(request: HttpRequest): com.hexagontk.http.model.HttpRequest {
  20.         val uri = URI(request.uri)
  21.         val qp =
  22.             request.queryParameters?.flatMap { (k, v) -> v.map { Parameter(k, it) } } ?: emptyList()
  23.         val h = request.headers?.flatMap { (k, v) -> v.map { Header(k, it) } } ?: emptyList()
  24.         val contentType = request.contentType.map { parseContentType(it) }.orElse(null)
  25.         val accept = request.headers["accept"]?.map { parseContentType(it) } ?: emptyList()
  26.         val authorization = request.headers["authorization"]
  27.             ?.first()
  28.             ?.split(" ", limit = 2)
  29.             ?.let { Authorization(it.first(), it.last()) }

  30.         // TODO Fix parts upload
  31.         val parts = emptyList<HttpPart>()
  32. //            if (request.contentType.orElse("").contains("multipart")) {
  33. //                request.parts.map { (k, v) ->
  34. //                    HttpPart(
  35. //                        name = k,
  36. //                        body = v.inputStream.readAllBytes(),
  37. //                        headers = Headers(),
  38. //                        contentType = v.contentType?.map { parseContentType(it) }?.orElse(null),
  39. //                        size = v.contentLength,
  40. //                        submittedFileName = v.fileName.orElse(null),
  41. //                    )
  42. //                }
  43. //            }
  44. //            else emptyList()

  45.         return HttpRequest(
  46.             method = HttpMethod.valueOf(request.method),
  47.             protocol = HttpProtocol.valueOf(uri.scheme.uppercase()),
  48.             host = uri.host,
  49.             port = uri.port,
  50.             path = request.path,
  51.             queryParameters = Parameters(qp),
  52.             headers = Headers(h),
  53.             body = request.inputStream.readAllBytes() ?: ByteArray(0),
  54.             parts = parts,
  55.             contentType = contentType,
  56.             accept = accept,
  57.             contentLength = request.contentLength,
  58.             authorization = authorization,
  59.         )
  60.     }

  61.     private fun writeResponse(response: HttpResponse, context: HttpContext) {
  62.         val handlerResponse = context.response

  63.         handlerResponse.contentType?.text?.let(response::setContentType)
  64.         handlerResponse.headers.forEach { response.appendHeader(it.name, it.text) }
  65.         response.setStatusCode(handlerResponse.status)

  66.         try {
  67.             response.outputStream.write(bodyToBytes(handlerResponse.body))
  68.         }
  69.         catch (e: Exception) {
  70.             response.setContentType(TEXT_PLAIN.fullType)
  71.             response.setStatusCode(500)
  72.             response.outputStream.write(bodyToBytes(e.toText()))
  73.         }
  74.     }
  75. }