Search code examples
scalarestakka-http

How to match path segments in URI with Akka-http low-level API


I'm trying to implement a REST API using the akka-http low-level API. I need to match a request for paths containing resource ids, for instance, "/users/12", where the 12 is the id of the user.

I'm looking for something along these lines:

case HttpRequest(GET, Uri.Path("/users/$asInt(id)"), _, _, _) =>
   // id available as a variable

The "$asInt(id)" is a made up syntax, I'm using it just to describe what I want to do.

I can easily find examples of how to do this with the high level API using routes and directives, but I can't find anything with the low-level API. Is this possible with the low-level API?


Solution

  • My team has found a nice solution to this:

    /** matches to "/{head}/{tail}" uri path, where tail is another path */
    object / {
      def unapply(path: Path): Option[(String, Path)] = path match {
        case Slash(Segment(element, tail)) => Some(element -> tail)
        case _ => None
      }
    }
    
    /** matches to last element of the path ("/{last}") */
    object /! {
      def unapply(path: Path): Option[String] = path match {
        case Slash(Segment(element, Empty)) => Some(element)
        case _ => None
      }
    }
    

    An example usage (where the expect path is "/event/${eventType}")

    val requestHandler: HttpRequest => Future[String] = {
      case HttpRequest(POST, uri, _, entity, _)  =>
          uri.path match {
            case /("event", /!(eventType)) =>
            case _ =>
         }
      case _ =>
    }
    

    More complex scenarios can be handled by chaining calls to /, ending with a call to /!.