Akka-Http

structible-akka-http is available for Scala 2.12 and 2.13.

It provides derivations for:

  • PathMatcher
  • Unmarshaller

Dependency

sbt
libraryDependencies += "com.github.cerst" % "structible-akka-http" % "0.4.0"
Maven
<dependency>
  <groupId>com.github.cerst</groupId>
  <artifactId>structible-akka-http</artifactId>
  <version>0.4.0</version>
</dependency>
Gradle
dependencies {
  compile group: 'com.github.cerst', name: 'structible-akka-http', version: '0.4.0'
}

PathMatcher Example

import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.{PathMatcher1, Route}
import com.github.cerst.structible.akkahttp.ops._
import com.github.cerst.structible.core.Structible

object PathMatcherExample {

  final case class PersonId(value: Long) {
    require(value >= 0, s"PersonId must be non-negative (got: '$value')")
  }

  object PersonId {

    // you can also pass-in 'construct' functions returning Either[String, A], Option[A] or Try[A]
    private val structible: Structible[Long, PersonId] = Structible.structible(PersonId.apply, _.value)

    // not declared as implicit because you usually call patch matchers explicitly within the Akka routing Dsl
    val pathMatcher: PathMatcher1[PersonId] = structible.toPathMatcher

  }

  val route: Route = {
    path("persons" / PersonId.pathMatcher) { personId =>
      complete(personId.toString)
    }
  }

}

Unmarshaller Example

This derivation was originally added to address a quirk in an Http Api which returned the id of a generated resource as plain text. Hence, the response entity needed to be unmarshalled directly as in Unmarshal(response.entity).to[A].
As long as you receive a properly formatted message, use a derivation for the employed messaging protocol and library (e.g. your favorite JSON library).

import akka.http.scaladsl.unmarshalling.{Unmarshal, Unmarshaller}
import akka.stream.Materializer
import com.github.cerst.structible.akkahttp.ops._
import com.github.cerst.structible.core.Structible

import scala.concurrent.{ExecutionContext, Future}

object UnmarshallerExample {

  final case class PersonId(value: Long) {
    require(value >= 0, s"PersonId must be non-negative (got: '$value')")
  }

  object PersonId {

    // you can also pass-in 'construct' functions returning Either[String, A], Option[A] or Try[A]
    private val structible: Structible[Long, PersonId] = Structible.structible(PersonId.apply, _.value)

    implicit val unmarshallerForPersonId: Unmarshaller[String, PersonId] = structible.toUnmarshaller

  }

  // this works seamlessly for e.g. HttpResponse.entity instead of String
  def toPersonId(input: String)(implicit ec: ExecutionContext, mat: Materializer): Future[PersonId] = {
    Unmarshal(input).to[PersonId]
  }

}
The source code for this page can be found here.