Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Request Content-Type in Play! Framework for REST webservices

I'm trying to implement a REST webservice with the Play! framework. I know how I can return a response in different formats (JSON, XML, HTML, ...) by specifying multiple templates. However, I didn't find any information on how you should process different Content-Types in a (e.g. POST) request (form encoded, JSON, XML, ...).

Is it possible to annotate a method to match only certain Content-Types (something like @Consumes)? Do I have to differentiate between the different request Content-Types with an if-clause in the controller method?

like image 237
raymi Avatar asked Mar 12 '12 22:03

raymi


People also ask

How do you set content type explicitly on play?

Changing the default Content-Type Will automatically set the Content-Type header to text/plain , while: JsonNode json = Json. toJson(object); Result jsonResult = ok(json); will set the Content-Type header to application/json .

What is WSClient?

WSClient is an enhancement of Rules web and Rules usecases (proof of concept modules).

What is play framework in Scala?

Play Framework makes it easy to build web applications with Java & Scala. Play is based on a lightweight, stateless, web-friendly architecture. Built on Akka, Play provides predictable and minimal resource consumption (CPU, memory, threads) for highly-scalable applications.


2 Answers

Have a look at the Play documentation for combining body parsers:

http://www.playframework.com/documentation/2.2.0/ScalaBodyParsers

If you want to constrain a post body to only xml or json you can write something along these lines:

val xmlOrJson = parse.using {
  request =>
    request.contentType.map(_.toLowerCase(Locale.ENGLISH)) match {
      case Some("application/json") | Some("text/json") => play.api.mvc.BodyParsers.parse.json
      case Some("application/xml") | Some("text/xml") => play.api.mvc.BodyParsers.parse.xml
      case _ => play.api.mvc.BodyParsers.parse.error(Future.successful(UnsupportedMediaType("Invalid content type specified")))
    }
}

def test = Action(xmlOrJson) {
  request =>
    request.body match {
      case json: JsObject => Ok(json) //echo back posted json
      case xml: NodeSeq => Ok(xml) //echo back posted XML
    }
}

The xmlOrJson function looks at the content type request header to determine the body parser. If it is not xml or json then it returns the error body parser with an UnsupportedMediaType response (HTTP 415).

You then pass this function in as the body parser of any action you want to constrain to xml or json content. Within the action you can look at the body to determine if xml or json was parsed and process accordingly.

like image 73
be.outside Avatar answered Oct 18 '22 14:10

be.outside


You don't do it through annotation, but rather through your routes file, or through an if statement in your action. Depends on your use case as to which one is best suited.

The following URL gives you some information on the routes file for content negotiation. http://www.playframework.org/documentation/1.2.4/routes#content-types

Example

GET    /index.xml         Application.index(format:'xml')  
GET    /index.json        Application.indexJson(format:'json')  

The above calls different actions, but you could call the same action with a different format value if you wish.

like image 39
Codemwnci Avatar answered Oct 18 '22 16:10

Codemwnci