parsing - Custom multipartFormData parser in play2 scala to handle multiple encodings on dataparts -


i'm trying implement custom multipartformdata data parser handle callback sendgrid api. callback multipart request dataparts encoded in different encodings: eg utf-8 or iso-8859-1.

sendgrid provides charsets field json object explains encoding each field have:

{"to":"utf-8","html":"iso-8859-1","subject":"utf-8","from":"utf-8","text":"iso-8859-1"} 

i extract charsets dataparts this:

    val charsets = extract(request.body.dataparts, "charsets", _.as[charsets]).getorelse(charsets(some(""), some(""), some(""), some(""), some("")))      def extract[t](env: map[string, seq[string]], key: string, conv: jsvalue => t): option[t] = {         env.get(key).flatmap(_.headoption).map(json.parse).map(conv)     }      case class charsets(to: option[string], html: option[string], subject: option[string], from: option[string], text: option[string])      object charsets {         implicit val charsetreads = json.format[charsets]     } 

but wont work since might have wrong encoding set parser.

the original handledatapart hardcoded use utf-8

def handledatapart: parthandler[part] = {     case headers @ multipart.partinfomatcher(partname) if !multipart.fileinfomatcher.unapply(headers).isdefined =>       traversable.takeupto[array[byte]](default_max_text_length)         .transform(iteratee.consume[array[byte]]().map(bytes => datapart(partname, new string(bytes, "utf-8"))))         .flatmap { data =>         cont({           case input.el(_) => done(maxdatapartsizeexceeded(partname), input.empty)           case in => done(data, in)         })       }   } 

so begin extract charsets object , use when creating dataparts or instead of creating string each field, create array[byte] , in controller handle creation of strings. maybe there other way? how solve this? feel stuck , need guidance.

got answer buddy tor! works charm!

class parser @inject()(mailrequestservice: mailrequestservice, surveyservice: surveyservice) extends controller {    val utf8 = "utf-8"    def parsemail = action.async(rawformdata) { request =>     val charsets = extract(request.body.dataparts, "charsets", _.as[charsets]).getorelse(charsets(some(""), some(""), some(""), some(""), some("")))     val envelope = extract(request.body.dataparts, "envelope", _.as[envelope]).getorelse(envelope(nil, ""))     val sendgrid = sendgridmail(       extractstring(request.body.dataparts, "text", charsets),       extractstring(request.body.dataparts, "html", charsets),       extractstring(request.body.dataparts, "from", charsets),       extractstring(request.body.dataparts, "to", charsets),       charsets,       envelope     )      val simple = mailrequestservice.createnewmail(sendgrid).map {       result =>         result.fold(           exception => throw new unexpectedserviceexception("could not save sendgrid mail: "+sendgrid, exception),           mail => ok("success")         )     }     simple   }    def extractstring(data: map[string, seq[array[byte]]], key: string, charsets: charsets): option[string] = {     play.logger.info("data = " + data)     data.get(key).flatmap(_.headoption).map { firstvalue =>       (charsets, key) match {         case (charset, "text") if charset.text.isdefined =>           val cset = java.nio.charset.charset.forname(charset.text.get)           some(new string(firstvalue, cset))         case (charset, "html") if charset.html.isdefined =>           val cset = java.nio.charset.charset.forname(charset.html.get)           some(new string(firstvalue, cset))         case (charset, "from") if charset.from.isdefined =>           val cset = java.nio.charset.charset.forname(charset.from.get)           some(new string(firstvalue, cset))         case (charset, "to") if charset.to.isdefined =>           val cset = java.nio.charset.charset.forname(charset.to.get)           some(new string(firstvalue, cset))         case _ => some("")       }     }.getorelse(some(""))   }    /**    * 1. retrieve value key eg. envelope    * 2. use flatmap flatten structure not option[option[_] ]    * 3. call map , use jsonparse on string jsvalue    * 4. call map , use provided method eg _.as[envelope] results in t, in case envelope    * 5. return!    */   def extract[t](env: map[string, seq[array[byte]]], key: string, conv: jsvalue => t): option[t] = {     env.get(key).flatmap(_.headoption.map(a => new string(a, "utf-8"))).map(json.parse).map(conv)   }    def findsurveybyemail(email: string): future[option[survey]] = {     surveyservice.findsurveybyemail(email)   }    def handler: parse.multipart.parthandler[part] = {     case headers @ partinfomatcher(partname) if !fileinfomatcher.unapply(headers).isdefined =>       traversable.takeupto[array[byte]](1024 * 100)         .transform(iteratee.consume[array[byte]]().map(bytes => filepart(partname, "", none, bytes)))         .flatmap { data =>         cont({           case input.el(_) => done(data, input.empty)           case in => done(data, in)         })       }     case headers => done(badpart(headers), input.empty)   }    def rawformdata[a]: bodyparser[rawdataformdata] = bodyparser("multipartformdata") { request =>     multipart.multipartparser(handler)(request).map { errororparts =>       errororparts.right.map { parts =>         val data = parts.collect { case filepart(key, _, _, value: array[byte]) => (key, value) }.groupby(_._1).mapvalues(_.map(_._2))         rawdataformdata(data)       }     }   } }  case class rawdataformdata(dataparts: map[string, seq[array[byte]]]) 

thank tor!


Comments

Popular posts from this blog

c# - DetailsView in ASP.Net - How to add another column on the side/add a control in each row? -

javascript - firefox memory leak -

Trying to import CSV file to a SQL Server database using asp.net and c# - can't find what I'm missing -