Reputation: 380
I'm relatively new to functional programming in scala. I came across the flowing method. I have been unable to figure out exactly what it is doing?
def getPostsByFilters = (authenticatedPublicApiPostArticleAction andThen rateLimitedApiAction).async(BodyParsers.parse.tolerantJson) { implicit request =>
implicit val apiKey = Some(request.apiKey)
request.body.validate[ArticlePostQuery] fold(
errors => futureBadRequest(errors.toString()),
articleQuery => verifyPostQueryParams(articleQuery, verifiedApiRequest => {
val PostsNetwork = PostsNetwork(true, verifiedApiRequest.contentType, verifiedApiRequest.orderBy)
apiArticleService.findApiArticlesWithPostRequest(verifiedApiRequest, PostsNetwork) map (articles => wrapUpResultsToJson(ApiPosts(articles)))
}))
}
It is in a play API controller and the method is mapped to a post request in the route file.
I know it take a json post request and returns a json response, but can someone explain what is actually happening and if there is a way to refactor it to make it more readable?
Upvotes: 0
Views: 52
Reputation: 149608
Dislaimer: I am not familiar with this piece of code. My reply is an attempt to help decipher the method invocations in an attempt to help you understand it better.
This method seems to be doing a couple of things.
Authentication and rate limiting - This is done by
authenticatedPublicApiPostArticleAction andThen rateLimitedApiAction
Note andThen
is used for composing functions from left to right. So first authentication is being done, and then rate limiting
Asynchrnous JSON parsing:
async(BodyParsers.parse.tolerantJson)
Attempts to parse the body of the HTTP requests as a JSON regarding the passed in Content-Type header.
Validation of the body:
request.body.validate[ArticlePostQuery]
This appears to be validating the body (JSON) matches the structure of ArticlePostQuery
(which I assume is a case class).
The validate method returns a JsResult
, which is an ADT (Algebraic Data Type), which may be either JsSuccess
or JsError
. The fold
method is used to handle both the error case (the first function) or the success case (second function).
Acting upon result:
If the former happens, the API returns an error status code (I assume some sort of 400 bad request with the error:
errors => futureBadRequest(errors.toString())
If the latter happens it attempts to verify that all query parameters exist:
articleQuery => verifyPostQueryParams(articleQuery, verifiedApiRequest
If they do exist, it invokes the following thunk:
val PostsNetwork =
PostsNetwork(
true,
verifiedApiRequest.contentType,
verifiedApiRequest.orderBy
)
apiArticleService
.findApiArticlesWithPostRequest(verifiedApiRequest, PostsNetwork)
.map(articles => wrapUpResultsToJson(ApiPosts(articles)))
}))
To retrieve the article posts. Then, it maps over the result to return a JSON result from an ApiPosts
object.
Upvotes: 2