Unable to parse a string in incoming request body if the Content-Type is text/html and the body contains any special characters

If I am sending a request to my Play+Scala server (2.5.x, 2.11.11) having HTML content in its body then I am not able to parse any special characters in request body using “request.body.asText.get”. Also if the Content-Type is set to text/html then Play server rejects the request with 500. Only when the Content-Type is text/plain Play parses the body.
NOTE: The request body contains string having special chars such as fraction: “T 2 ⅜ 01/31/23”
Any suggestions ?

Can you include more details about the code on both client and server side?

Action Controller on the server:

class SendPreviewEmailController @Inject() (
   mailer: Mailer,
   val authorizationHandler: AuthorizationHandler,
   val messagesApi: MessagesApi)
   (implicit context: ExecutionContext)
   extends Controller with AuthorizationCheck with I18nSupport {
	def sendPreviewEmail = AuthenticatedAction.async { implicit request =>
      val token: String = request.headers.get("token").get
      val payload: String = JwtTokenService.decodePayload(token).get
      val json: JsValue = Json.parse(payload)
      val email = (json \ "email").as[String]
      val name = (json \ "name").as[String]
       /* Why Content-Type as text/html does not work ??
       */
	   mailer.previewEmail(name, email, request.body.asText.get)
	   Future(Ok("success"))
	}
}

The client code snippet:

const config = {
		headers: {"Content-Type": "text/plain"}
		};
	axios.post('/sendpreviewemail',emailContent, config)

Snippet of the HTML content (sent as emailContent):

</tr><tr>	<td style='width:140px;padding:3px 15px;background-color:#f3f3f3;font-family:Arial;font-size:13px;border-right:1px solid #ccc;border-bottom:1px solid #ccc'>Treasury Benchmark</td>	<td style='color:#616161;padding:3px 15px;font-family:Arial;font-size:13px;border-bottom:1px solid #ccc'>T 2 ⅜ 01/31/23</td>

It may be because the default encoding is ISO-8859-1 unless you supply a charset in the Content-Type.

You could work around this by using AuthenticatedAction.async(parse.raw) { ... } and then converting the bytes manually into a string.

Thanks Rich for your suggestions. I tried two things where one worked and other didn’t.

  1. Sent Content-Type value “text/plain;charset=utf-8”. This worked successfully allowing parsing of special chars using ```
    request.body.asText.get
2. When sending Content-Type as "text/html" or "text/html;charset=utf-8" Play returns 500 error.

Question: I am missing the point that why there is no specific parser for Content-Type as "text/html" ? Only Raw() works which is anyway generic.

Glad it’s working. The reason there’s no specific content parser for text/html is simply that no one has written one. That’s probably because it’s not very common to parse incoming HTML when you’re writing a server app.