import com.twitter.finagle.Http import com.twitter.util.{Await, Future} import io.finch._ import io.finch.syntax._ import io.finch.circe.accumulating._ import io.circe._ import io.circe.generic.auto._ case class RequestBody(foo: Boolean, bar: Int) case class FakeResponse() object Main extends App { implicit val encodeException: Encoder[Exception] = Encoder.instance({ case e: io.finch.Errors => encodeErrorList(e.errors.toList) case e: io.finch.Error => e.getCause match { case e: io.circe.Errors => encodeErrorList(e.errors.toList) case err => Json.obj("message" -> Json.fromString(err.getMessage)) } case e: Exception => Json.obj("message" -> Json.fromString(s"Oh noes! ${e.getMessage}")) }) def encodeErrorList(es: List[Exception]): Json = { val messages = es.map(x => Json.fromString(x.getMessage)) Json.obj("errors" -> Json.arr(messages: _*)) } def fakeServiceMethod(requestBody: RequestBody): Future[Output[FakeResponse]] = Future.value(Ok(FakeResponse())) val fooEndpoint: Endpoint[FakeResponse] = post("foo" :: jsonBody[RequestBody])(fakeServiceMethod _) Await.ready(Http.server.serve(":8080", fooEndpoint.toServiceAs[Application.Json])) }