Let's say I define this route using Akka Http:
- POST method
- If there's a specific
header
in therequest
I will remove it but I will add a newheader
with the same value (it is like I'm replacing aheader
in therequest
). I'm using a customdirective
here. - Extract the body as a
case class
(SomeData) - Finally inside the
complete
block I have some code that uses therequest
(with theheaders
processed in step 2)
It would be something like this:
val someRoute = replaceHeaders {
post {
extractRequest { req =>
entity(as[SomeData]) { someData =>
complete {
// some code here that uses `req` (defined 3 lines above)
}
}
}
}
}
For replacing headers
I can define a custom directive
, similar to this:
def replaceHeaders: Directive0 =
mapRequest(req =>
req.headers.find(_.is(headerToReplace)) match {
case Some(header) =>
req
.removeHeader(...)
.addHeader(...(header.value()))
case None => req
}
)
In the first code inside the complete
block I have access to the request
, in particular I have access to the headers
that has been processed by replaceHeaders directive
.
How can I do the same using http4s
library? Because there are no customized directive
as in Akka Http
.
I know I can create a function to do something similar:
def replaceHeaders(request: Request[IO]): Headers = {
val searchHeader = "SomeHeader"
val newHeader = "NewHeader"
request.headers.get(CaseInsensitiveString(searchHeader)) match {
case Some(headerFound) =>
request.headers
.filterNot(_.name == CaseInsensitiveString(searchHeader))
.put(Header(newHeader, headerFound.value))
case None =>
request.headers
}
}
val routes: HttpRoutes[IO] = {
val dsl = Http4sDsl[IO]
import dsl._
HttpRoutes.of[IO] {
case req @ POST -> Root =>
// replace one header for another
val newHeaders = replaceHeaders(req)
IO {
Response[IO](Status.Ok)
.withHeaders(newHeaders)
.withEntity[String]("Process ok.")
}
}
}
But in this case I have a new collection of headers
: val newHeaders = replaceHeaders(req)
.
But Akka Http
is more flexible, when I make changes to the headers
these are immediately available as part of the request
after extractRequest
. Every block after extractRequest
when accessing the request
will have the headers
updated.
But in the case of http4s
(at least in my code) I have to explicitly use newHeaders
to access the new headers
.
How can I do the same in http4s
?