1717package feral .lambda
1818package http4s
1919
20+ import cats .data .OptionT
2021import cats .effect .kernel .Concurrent
2122import cats .syntax .all ._
2223import feral .lambda .events .ApiGatewayProxyEventV2
2324import feral .lambda .events .ApiGatewayProxyStructuredResultV2
24- import fs2 .Stream
25+ import fs2 .Chunk
2526import org .http4s .Charset
27+ import org .http4s .Entity
2628import org .http4s .Headers
2729import org .http4s .HttpRoutes
30+ import org .http4s .MalformedMessageBodyFailure
2831import org .http4s .Method
2932import org .http4s .Request
3033import org .http4s .Response
3134import org .http4s .Uri
3235import org .http4s .headers .Cookie
3336import org .http4s .headers .`Set-Cookie`
37+ import scodec .bits .ByteVector
3438
3539object ApiGatewayProxyHandler {
3640
@@ -39,15 +43,21 @@ object ApiGatewayProxyHandler {
3943 for {
4044 event <- LambdaEnv .event
4145 request <- decodeEvent(event)
42- response <- routes(request).getOrElse(Response .notFound[ F ] )
46+ response <- routes(request).getOrElse(Response .notFound)
4347 isBase64Encoded = ! response.charset.contains(Charset .`UTF-8`)
44- responseBody <- response
45- .body
46- .through(
47- if (isBase64Encoded) fs2.text.base64.encode else fs2.text.utf8.decode
48- )
49- .compile
50- .string
48+ responseBody <- response.entity match {
49+ case Entity .Empty => " " .pure
50+ case Entity .Strict (chunk) => // TODO
51+ if (isBase64Encoded) chunk.toByteVector.toBase64.pure
52+ else chunk.toByteVector.decodeUtf8.liftTo
53+ case Entity .Default (body, _) =>
54+ body
55+ .through(
56+ if (isBase64Encoded) fs2.text.base64.encode else fs2.text.utf8.decode
57+ )
58+ .compile
59+ .string
60+ }
5161 } yield {
5262 val headers = response.headers.headers.groupMap(_.name)(_.value)
5363 Some (
@@ -70,15 +80,22 @@ object ApiGatewayProxyHandler {
7080 uri <- Uri .fromString(event.rawPath + " ?" + event.rawQueryString).liftTo[F ]
7181 cookies = event.cookies.filter(_.nonEmpty).map(Cookie .name.toString -> _.mkString(" ; " ))
7282 headers = Headers (cookies.toList ::: event.headers.toList)
73- readBody =
74- if (event.isBase64Encoded)
75- fs2.text.base64.decode[F ]
76- else
77- fs2.text.utf8.encode[F ]
83+ body <- OptionT
84+ .fromOption(event.body)
85+ .semiflatMap { eventBody =>
86+ if (event.isBase64Encoded)
87+ ByteVector
88+ .fromBase64Descriptive(eventBody)
89+ .leftMap(MalformedMessageBodyFailure (_))
90+ .liftTo
91+ else
92+ ByteVector .encodeUtf8(eventBody).liftTo
93+ }
94+ .value
7895 } yield Request (
7996 method,
8097 uri,
8198 headers = headers,
82- body = Stream .fromOption[ F ](event.body).through(readBody )
99+ entity = body.foldMap(b => Entity .strict( Chunk .byteVector(b)) )
83100 )
84101}
0 commit comments