diff --git a/lambda-http4s/src/main/scala/feral/lambda/http4s/ApiGatewayProxyHandler.scala b/lambda-http4s/src/main/scala/feral/lambda/http4s/ApiGatewayProxyHandler.scala index 152303a5..a207bcc0 100644 --- a/lambda-http4s/src/main/scala/feral/lambda/http4s/ApiGatewayProxyHandler.scala +++ b/lambda-http4s/src/main/scala/feral/lambda/http4s/ApiGatewayProxyHandler.scala @@ -32,6 +32,7 @@ import org.http4s.HttpRoutes import org.http4s.Method import org.http4s.Request import org.http4s.Uri +import org.typelevel.ci.CIString object ApiGatewayProxyHandler { @@ -63,24 +64,13 @@ object ApiGatewayProxyHandler { event: ApiGatewayProxyEvent): F[Request[F]] = { val queryString: String = getMultiValueQueryStringParameters( event.multiValueQueryStringParameters) + val uriString: String = event.path + (if (queryString.nonEmpty) s"?$queryString" else "") for { method <- Method.fromString(event.httpMethod).liftTo[F] uri <- Uri.fromString(uriString).liftTo[F] - headers = { - val builder = List.newBuilder[Header.Raw] - event.headers.foreach { h => h.foreachEntry(builder += Header.Raw(_, _)) } - event.multiValueHeaders.foreach { hMap => - hMap.foreach { - case (key, values) => - if (!event.headers.exists(_.contains(key))) { - values.foreach(value => builder += Header.Raw(key, value)) - } - } - } - Headers(builder.result()) - } + headers = Headers(getMultiValueHeaders(event.multiValueHeaders)) readBody = if (event.isBase64Encoded) fs2.text.base64.decode[F] @@ -105,6 +95,15 @@ object ApiGatewayProxyHandler { .mkString("&") } + private def getMultiValueHeaders( + multiValueHeaders: Option[Map[CIString, List[String]]]): List[Header.Raw] = { + for { + headerMap <- multiValueHeaders.toList + (key, values) <- headerMap + headerRaw <- values.map(value => Header.Raw(key, value)) + } yield headerRaw + } + @deprecated("Use ApiGatewayProxyHandlerV2", "0.3.0") def apply[F[_]: ApiGatewayProxyInvocationV2: Concurrent]( routes: HttpRoutes[F]): F[Option[ApiGatewayProxyStructuredResultV2]] = httpRoutes(routes) diff --git a/lambda-http4s/src/test/scala/feral/lambda/http4s/ApiGatewayProxyHandlerSuite.scala b/lambda-http4s/src/test/scala/feral/lambda/http4s/ApiGatewayProxyHandlerSuite.scala index 7d31505c..72602062 100644 --- a/lambda-http4s/src/test/scala/feral/lambda/http4s/ApiGatewayProxyHandlerSuite.scala +++ b/lambda-http4s/src/test/scala/feral/lambda/http4s/ApiGatewayProxyHandlerSuite.scala @@ -37,6 +37,8 @@ class ApiGatewayProxyHandlerSuite extends CatsEffectSuite { "X-Amz-Cf-Id" -> "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==", "Host" -> "1234567890.execute-api.us-east-1.amazonaws.com", "Accept-Encoding" -> "gzip, deflate, sdch", + "X-MultiHeader" -> "foo", + "X-MultiHeader" -> "bar", "X-Forwarded-Port" -> "443", "Cache-Control" -> "max-age=0", "CloudFront-Viewer-Country" -> "US", @@ -57,7 +59,7 @@ class ApiGatewayProxyHandlerSuite extends CatsEffectSuite { event <- event.as[ApiGatewayProxyEvent].liftTo[IO] request <- ApiGatewayProxyHandler.decodeEvent[IO](event) _ <- IO(assertEquals(request.method, Method.POST)) - _ <- IO(assertEquals(request.uri, uri"/path/to/resource?foo=bar")) + _ <- IO(assertEquals(request.uri, uri"/path/to/resource?foo=bar&foo=baz")) _ <- IO(assertEquals(request.headers, expectedHeaders)) responseBody <- request.bodyText.compile.string _ <- IO(assertEquals(responseBody, expectedBody)) diff --git a/lambda/shared/src/test/scala/feral/lambda/events/ApiGatewayProxyEventSuite.scala b/lambda/shared/src/test/scala/feral/lambda/events/ApiGatewayProxyEventSuite.scala index 1ff531f7..23ec2736 100644 --- a/lambda/shared/src/test/scala/feral/lambda/events/ApiGatewayProxyEventSuite.scala +++ b/lambda/shared/src/test/scala/feral/lambda/events/ApiGatewayProxyEventSuite.scala @@ -43,7 +43,8 @@ object ApiGatewayProxyEventSuite { }, "multiValueQueryStringParameters": { "foo": [ - "bar" + "bar", + "baz" ] }, "pathParameters": { @@ -70,7 +71,8 @@ object ApiGatewayProxyEventSuite { "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==", "X-Forwarded-For": "127.0.0.1, 127.0.0.2", "X-Forwarded-Port": "443", - "X-Forwarded-Proto": "https" + "X-Forwarded-Proto": "https", + "X-MultiHeader": "foo" }, "multiValueHeaders": { "Accept": [ @@ -126,6 +128,10 @@ object ApiGatewayProxyEventSuite { ], "X-Forwarded-Proto": [ "https" + ], + "X-MultiHeader": [ + "foo", + "bar" ] }, "requestContext": {