scalaroutesgethttp4spartial-functions

http4s route matching for GET requests with params on root host


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.


Solution

  • 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.