scala - EssentialAction: How to Get the Body of a Request without Parsing It -


given following essentialaction...

object mycontroller extends controller {    ...    def hastoken(action: token => essentialaction) = essentialaction { request =>      ...      // doesn't compile     val body = request.body match {       case json: jsvalue => json.tostring       case _ => ""     }      // calculate hash body content here     ...   }    // here authenticated action   def getuser(userid: strign) = hastoken { token =>     action(parse.json) { request =>       request.body.validate[user] match {         ...       }     }   } } 

... how body of request without parsing it?

i don't want , don't need parse request body in hastoken since body going parsed in action getuser. need raw content of body calculate hash.

the code in hastoken doesn't compile because request of type requestheader whereas need request, defines body.

will work ?

object mycontroller extends controller {    // hastoken action   def authenticate(action: token => essentialaction) = essentialaction { requestheader =>     // ... execute logic verify authenticity using requestheader   }    // action validate tampering of request body , validity of json   def validate[a](action: token => request[a]) = action(parse.json) { request =>     val body = request.body     body match {       case json: jsvalue => json.tostring       case _ => ""     }     // calculate hash body content here      body.validate[user] match {       // ...     }   }    def getuser(userid: strign) = authenticate { token =>     validate { user =>       //.... continue     }   } } 
  • authentication uses requestheader
  • validation uses request body. (bonus: body parsed once)

edit:

question #1: don't want validate body in validate... since need generic validation mechanism used everywhere regardless of content type (e.g. user, message, etc.).

how adding type param (so made generic):

def validate[a, b](action: token => request[a])(implicit reads: reads[b]) = action(parse.json) { request =>    // ... } 

question #2: furthermore, if token validation fails, body don't have processed (that's important in case of file upload, has performed if , if validation succeeded). that's way, in opinion, best option read raw content of body in validate.

this can achieved:

def validate[a, b](action: token => request[a])(implicit reads: reads[b]) = action(parse.json) { request =>    val body = request.body     body match {       case json: jsvalue => json.tostring       case _ => ""     }     // calculate hash body content here , figure out if body tampered     if (bodyisnottampered) {       body.validate[b] match {         // ...       }     } else {       // log , return future.successful(badrequest)     }   } 

edit 3: full solution:

import play.api.libs.json.{json, jsvalue, format}  object compilationutils {   class token   case class user(name: string)   implicit val userformat = json.format[user]    def authenticate = new token // authentication logic    def istampered(body: jsvalue) = {     val bodyasstr: string = json.stringify(body)     // calculate hash body content here     false   }  }  object mycontroller extends controller {   import compilationutils._    // hastoken action   def authenticate(action: token => essentialaction) = essentialaction { requestheader =>     action(authenticate)(requestheader) // execute logic verify authenticity using requestheader   }    // action validate tampering of request body , validity of json   def validate[a, b](request: request[a])(implicit formata: format[a], formatb: format[b]): either[result, b] = {     val body = request.body     val bodyasjsvalue = json.tojson(body)     if (!istampered(bodyasjsvalue)) {       bodyasjsvalue.validate[b].fold(         valid   = res => right(res),         invalid = err => left(badrequest(err.tostring))       )     } else {       left(badrequest) // request tampered     }   }    def getuser(userid: string) = authenticate { token =>     action(parse.json) { request =>       validate(request).fold(         badreq => badreq,         user   =>           // continue...           ok("")       )     }   } } 

Comments

Popular posts from this blog

python - TypeError: start must be a integer -

c# - DevExpress RepositoryItemComboBox BackColor property ignored -

django - Creating multiple model instances in DRF3 -