Skip to content

Instantly share code, notes, and snippets.

@davidmweber
Last active August 29, 2015 13:57
Show Gist options
  • Save davidmweber/9808705 to your computer and use it in GitHub Desktop.
Save davidmweber/9808705 to your computer and use it in GitHub Desktop.
Using Spray to return different marshalling formats based on an Accept type in the request header
import org.scalatest.{FunSpec, Matchers}
import spray.http.HttpHeaders.Accept
import spray.http.HttpEntity
import spray.http.MediaTypes._
import spray.httpx.marshalling._
import spray.routing.Directives._
import spray.routing.HttpService.sealRoute
import spray.testkit.ScalatestRouteTest
import spray.json._
import spray.httpx.SprayJsonSupport._
// All the fuss is about this...
case class Order(name: String, no: Int)
// Custom marshalling for our text/plain
object OurMarshaller extends DefaultJsonProtocol {
// You must explicitly type jsonOrder as a Marshaller[T]
val jsonOrder: Marshaller[Order] = jsonFormat2(Order)
val textOrder = Marshaller.of[Order](`text/plain`) {
(value, content, ctx) => ctx.marshalTo(HttpEntity(content, value.toString))
}
implicit val orderMarshal: ToResponseMarshaller[Order] =
ToResponseMarshaller.oneOf(`application/json`, `text/plain`)(jsonOrder, textOrder)
}
class TestMarshalByAccept extends FunSpec with ScalatestRouteTest with Matchers {
import OurMarshaller._
// Marshals response according to the Accept header media type
val fetchOrder = path("order" / IntNumber) {
id => get {
complete(Order("Bender", id))
}
}
describe("Our route should") {
val str = """{
| "name": "Bender",
| "no": 1234
|}""".stripMargin
it("return a json if requested") {
Get("/order/1234").withHeaders(Accept(`application/json`)) ~> fetchOrder ~> check {
contentType.mediaType.toString() should equal(Accept(`application/json`).value)
responseAs[String] should equal(str)
}
}
it("return text if requested") {
Get("/order/1235").withHeaders(Accept(`text/plain`)) ~> fetchOrder ~> check {
contentType.mediaType.toString should equal(Accept(`text/plain`).value)
responseAs[String] should equal(Order("Bender", 1235).toString)
}
}
it("fail with unknown media types") {
Get("/order/1234").withHeaders(Accept(`text/html`)) ~> sealRoute(fetchOrder) ~> check {
status.intValue should equal(406)
}
}
it("give us json with no Accept header") {
Get("/order/1234") ~> sealRoute(fetchOrder) ~> check {
contentType.mediaType.toString should equal(Accept(`application/json`).value)
println(responseAs[String])
responseAs[String] should equal(str)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment