Play module for RESTful HTTP Content Negotiation. Lets you define a mapping from your domain objects to different representations:
def jsonTransform(s: String) = toJson(Map("message" -> toJson(s)))
def jsonpTransform(s: String, r: Request[Any]) = {
val callback = r.queryString.getOrElse("callback", Nil).headOption
.getOrElse("callback")
Jsonp(callback, jsonTransform(s))
}
val m = mapping(
"text/html" -> { s: String => views.html.index(s) },
"application/xml" -> { s: String => <message>{s}</message> },
"application/json" -> jsonTransform _,
"text/javascript" -> jsonpTransform _,
"text/plain" -> identity[String]_
)
You can then reuse that mapping in your controllers without polluting the domain logic:
object Application extends Controller {
def index = Action { implicit request =>
m.status(200)("Hello, world!")
}
}
and let mimerender
take care of the rest:
$ # no accept header, gets the first representation (text/html)
$ curl -i localhost:9000
HTTP/1.1 200 OK
Content-Type: text/html
Vary: Accept
Content-Length: 130
<!doctype html>
<html>
<head>
<title>Hello, world!</title>
</head>
<body>
<h1>Hello, world!</h1>
</body>
</html>
$ # a simple text/plain accept header resolves to text/plain
$ curl -iH "Accept: text/plain" localhost:9000
HTTP/1.1 200 OK
Content-Type: text/plain
Vary: Accept
Content-Length: 13
Hello, world!
$ # */json;q=0.5,*/xml;q=1.0,*/*;q=0.1 resolves to application/xml
$ curl -iH "Accept: */json;q=0.5,*/xml;q=1.0,*/*;q=0.1" localhost:9000
HTTP/1.1 200 OK
Content-Type: application/xml
Vary: Accept
Content-Length: 32
<message>Hello, world!</message>
$ # application/octet-stream is not supported and it fails like it's supposed to
$ # (but you can override this)
$ curl -iH "Accept: application/octet-stream" localhost:9000
HTTP/1.1 406 Not Acceptable
Content-Type: text/plain; charset=utf-8
Vary: Accept
Content-Length: 150
None of the supported types (text/html, application/xml, application/json,
text/plain) is acceptable for the Acccept header 'application/octet-stream'
$ # text/javascript produces jsonp with a user-specified callback
$ curl -iH "Accept: text/javascript" "localhost:9000/?callback=callMe"
HTTP/1.1 200 OK
Content-Type: text/javascript
Vary: Accept
Content-Length: 36
callMe({"message":"Hello, world!"});
There's really not much more to it, except looking at the samples
directory.
Just add the dependency and the resolver in your Build.scala
:
val appDependencies = Seq(
"mimerender" %% "mimerender" % "0.1.2"
)
val main = PlayProject(appName, appVersion, appDependencies).settings(
resolvers +=
Resolver.url("mimerender github repo",
url("http://martinblech.github.com/play-mimerender/releases")
)(Resolver.ivyStylePatterns)
)
play-mimerender
is a loose Play! 2 port of the Python
mimerender module.
See LICENSE