I have simple rout-mapping function which using http4s
:
import cats.syntax.all._
import org.http4s._
import org.http4s.circe._
def routeMapper: PartialFunction[Request[F], F[Response[F]]] = {
case r @ POST -> Root => create
case r @ PUT -> Root / id => update(id)
case GET -> Root :? Published(published) => searchByPublishedDate(published)
case GET -> Root =>
println("show all called")
showAll
case GET -> Root / id => searchById(id)
case DELETE -> Root => deleteAll
case DELETE -> Root / id => delete(id)
}
object Published extends QueryParamDecoderMatcher[String]("published")
// I use this rout mapper to create HttpRoutes for HttpServer
def routes: HttpRoutes[F] = HttpRoutes.of[F](routeMapper)
For some reason when I try to pass GET request with some param which is not published
to my server, I see result of showAll
method.
For example, if I send get request on http://{host}:{port}/?foo=somevalue
I expect to see something like org.http4s.dsl.impl.Status.BadRequest
or org.http4s.dsl.impl.Status.NotFound
in Response
but I see that it matches case GET -> Root
actually.
Why it happens and how I can avoid this matching?
As I got partial functions are used for such cases when we want to define function only for some specified arguments (or types) but not for all possible inputs.
As already mentioned in comments, case case GET -> Root =>
will match all requests for the root path regardless of extra parameters.
To make this check stricter you could just reject that case if there's any parameter:
case request @ GET -> Root if request.params.isEmpty =>
it will match only if params map is empty.