0

Is it possible to validate the POST body in Akka Http?

Case Class Validationseems to work only for get requests.

As an example:

case class User(name: String){
    require(name)
}
 ..... 
(post & entity(as[User])) { user =>
            complete(doSomething(user.name))
          }

I would like the above code to throw a ValidationRejection rejection

EugeneMi
  • 3,475
  • 3
  • 38
  • 57

1 Answers1

1

You can use require inside scope of complete directive

(path("stats") & parameter("idsParam")) { idsParam =>
    complete {
      require(idsParam.length > 1)
      val ids = idsParam.split(",").map(v => CaseId(v).value)
      DBManager.getArticleStats(ids).map { case (id, stats) => IdWithValue(CaseId(id), stats) }
    }
}

that handles yours POST request.

And typically I have custom exception handler that wraps all exceptions into format that my API client expects such as json. require throws IllegalArgumentException so let's handle it in special way if we want to.

protected implicit def myExceptionHandler =
  ExceptionHandler {
    case ex: IllegalArgumentException => ctx => {
      val cause = ex.getCause
      ex.printStackTrace()
      ctx.complete(StatusCodes.InternalServerError, ErrorResponse(ex.code, ex))
    }
    case ex: Throwable => ctx =>
      logger.warning("Request {} could not be handled normally", ctx.request)
      ex.printStackTrace()
      ctx.complete(StatusCodes.InternalServerError, ErrorResponse(StatusCodes.InternalServerError.intValue, ex))
  }

where ErrorResponse is my case class that is being serialized to json using spray-json

expert
  • 29,290
  • 30
  • 110
  • 214
  • Thanks. Mind sharing an example? Not quite sure how to use require inside of complete – EugeneMi Oct 24 '16 at 22:06
  • Sure thing. Added. – expert Oct 24 '16 at 22:20
  • Thanks! Isn't require suppose to throw ValidationRejection? – EugeneMi Oct 24 '16 at 22:29
  • Nope, `require` is general helper function. It's not related to `akka-http` per se. – expert Oct 24 '16 at 22:30
  • There is http://doc.akka.io/docs/akka/2.4.3/scala/http/routing-dsl/case-class-extraction.html#Case_Class_Validation . But I guess it works only for GET params – EugeneMi Oct 24 '16 at 22:52
  • For some reason ExceptionHandler is not getting called, and IllegalArgumentException is not getting cause in my Akka Route tests. Tried both explicit and implicit ExceptionHandler – EugeneMi Oct 24 '16 at 22:53
  • Yep, but `require` is defined in `scala.Predef`. – expert Oct 24 '16 at 22:53
  • Hmmm not sure what to say. According to this http://doc.akka.io/docs/akka/2.4/scala/http/routing-dsl/exception-handling.html it should work. Maybe `myExceptionHandler` implicit is not declared somewhere where routes are defined. You can invoke your handler explicitly via `handleExceptions` directive. – expert Oct 24 '16 at 22:58