scalaoperatorspartialfunction

What is correct way to use operator orElse in Scala?


I want to write two services, and then use orElse to make the two services combine together, which means service_one or service_two. They are all PartialFunctions.

The service one is:

val usersService = HttpService {
case request @ GET -> Root / "users" / IntVar(userId) =>
  Ok("test")
}

The service two is:

val versionService = HttpService{
  case req @ GET -> Root / "version" => {
    val jsonmap = ("origin" -> req.remoteAddr.getOrElse("unknown ip"))
    Ok(compact(render(jsonmap)))
   }
}

and then I want to combine then together.

val service = userService orElse versionService   //the error happens here.

The error is:

[error] F:\workspace\frankcheckAPI\src\main\scala\com\cardaccess\ServiceApp.scala:46: value orElse is not a member of org.http4s.HttpService
[error]   val service = usersService orElse versionService
[error]                              ^
[error] one error found
[error] (compile:compileIncremental) Compilation failed

How to combine then make then works like if case match the first service's path the First service work, if the case match the second service's path. the second service work.

ps: as people concerned:

The HttpService object is define like:

  type HttpService = Service[Request, Response]
  object HttpService {

/** Alternative application which lifts a partial function to an `HttpService`,
  * answering with a [[Response]] with status [[Status.NotFound]] for any requests
  * where the function is undefined.
  */
def apply(pf: PartialFunction[Request, Task[Response]], default: HttpService = empty): HttpService =
  Service.lift(req => pf.applyOrElse(req, default))
...
}

Solution

  • orElse is used with PartialFunction, example:

    val t1: PartialFunction[Int, String] = {case 1 => "I am 1"}
    val t2: PartialFunction[Int, String] = {case 2 => "I am 2"}
    val t = t1 orElse t2
    t(1)
    > I am 1
    t(2)
    > I am 2
    

    As HttpService the apply method signature accept PartialFunction, I think you can do it maybe like:

    val usersService: PartialFunction[Request, Task[Response]] = {
      case request @ GET -> Root / "users" / IntVar(userId) =>
        Ok("test")
    }
    
    val versionService: PartialFunction[Request, Task[Response]] = {
      case req @ GET -> Root / "version" => {
        val jsonmap = ("origin" -> req.remoteAddr.getOrElse("unknown ip"))
        Ok(compact(render(jsonmap)))
       }
    }
    val service = HttpService {
      usersService orElse versionService
    }