Skip to content

Commit

Permalink
Add header echoing server middleware
Browse files Browse the repository at this point in the history
  • Loading branch information
keirlawson committed Aug 20, 2018
1 parent 867cb8c commit ec94e18
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 0 deletions.
@@ -0,0 +1,24 @@
package org.http4s.server.middleware

import cats.Functor
import cats.data.Kleisli
import org.http4s._

object HeaderEcho {

private def isOneOf(headerKeys: Seq[HeaderKey])(header: Header): Boolean =
headerKeys.exists(_.matchHeader(header).isDefined)

/**
* Simple server middleware that adds selected headers present on the request to the response.
*
* @param headerKeys the keys corresponding to the headers to echo on the response
* @param http [[HttpRoutes]] to transform
*/
def apply[F[_]: Functor](headerKeys: HeaderKey*)(http: HttpRoutes[F]): HttpRoutes[F] =
Kleisli { req: Request[F] =>
val headersToEcho = req.headers.filter(isOneOf(headerKeys))

http(req).map(_.putHeaders(headersToEcho.toList: _*))
}
}
@@ -0,0 +1,62 @@
package org.http4s.server.middleware

import cats.effect.IO
import org.http4s._
import org.http4s.dsl.io._

class HeaderEchoSpec extends Http4sSpec {

object someHeaderKey extends HeaderKey.Default
object anotherHeaderKey extends HeaderKey.Default

val testService = HttpRoutes.of[IO] {
case GET -> Root / "request" => Ok("request response")
}

"HeaderEcho" should {
"echo a single header in addition to the defaults" in {
val requestMatchingSingleHeaderKey =
Request[IO](
uri = uri("/request"),
headers = Headers(Header("someheaderkey", "someheadervalue")))
val testee = HeaderEcho(someHeaderKey)(testService)
val responseHeaders =
testee.orNotFound(requestMatchingSingleHeaderKey).unsafeRunSync().headers

responseHeaders.exists(_.value == "someheadervalue") must_== true
(responseHeaders must have).size(3)
}

"echo multiple headers" in {
val requestMatchingMultipleHeaderKeys =
Request[IO](
uri = uri("/request"),
headers = Headers(
Header("someheaderkey", "someheadervalue"),
Header("anotherheaderkey", "anotherheadervalue")))
val testee = HeaderEcho(someHeaderKey, anotherHeaderKey)(testService)

val responseHeaders =
testee.orNotFound(requestMatchingMultipleHeaderKeys).unsafeRunSync().headers

responseHeaders.exists(_.value == "someheadervalue") must_== true
responseHeaders.exists(_.value == "anotherheadervalue") must_== true
(responseHeaders must have).size(4)
}

"echo only the default headers where none match the key" in {
val requestMatchingNotPresentHeaderKey =
Request[IO](
uri = uri("/request"),
headers = Headers(Header("someunmatchedheader", "someunmatchedvalue")))

val testee = HeaderEcho(someHeaderKey)(testService)
val responseHeaders =
testee.orNotFound(requestMatchingNotPresentHeaderKey).unsafeRunSync().headers

responseHeaders.exists(_.value == "someunmatchedvalue") must_== false
(responseHeaders must have).size(2)
}
}

}

0 comments on commit ec94e18

Please sign in to comment.