How do i specify spray Content-Type response header?

12,294

Solution 1

If you still want to use spray can, then you have two options, based on that HttpResponse is a case class. The first is to pass a List with an explicit content type:

import spray.http.HttpHeaders._
import spray.http.ContentTypes._

def receive = {
    case HttpRequest(GET, Uri.Path("/something"), _, _, _) =>
      sender ! HttpResponse(entity = """{ "key": "value" }""", headers = List(`Content-Type`(`application/json`)))
  }

Or, the second way, is to use a method withHeaders method:

def receive = {
    case HttpRequest(GET, Uri.Path("/something"), _, _, _) =>
      val response: HttpResponse = HttpResponse(entity = """{ "key": "value" }""")
      sender ! response.withHeaders(List(`Content-Type`(`application/json`)))
  }

But still, like jrudolph said, it's much better to use spray routing, in this case it would look better:

def receive = runRoute {
    path("/something") {
      get {
        respondWithHeader(`Content-Type`(`application/json`)) {
          complete("""{ "key": "value" }""")
        }
      }
    }
  }

But spray makes it even easier and handles all (un)marshalling for you:

import spray.httpx.SprayJsonSupport._
import spray.json.DefaultJsonProtocol._

def receive = runRoute {
  (path("/something") & get) {
    complete(Map("key" -> "value"))
  }
}

In this case reponse type will be set to application/json by the spray itself.

Complete example for my comment:

class FullProfileServiceStack
  extends HttpServiceActor
     with ProfileServiceStack
     with ... {
  def actorRefFactory = context
  def receive = runRoute(serviceRoutes)
}

object Launcher extends App {
  import Settings.service._
  implicit val system = ActorSystem("Profile-Service")
  import system.log

  log.info("Starting service actor")
  val handler = system.actorOf(Props[FullProfileServiceStack], "ProfileActor")

  log.info("Starting Http connection")
  IO(Http) ! Http.Bind(handler, interface = host, port = port)
}

Solution 2

The entity parameter of HttpResponse is actually of type HttpEntity and your string is only implicitly converted into an instance of HttpEntity. You can use one of the other constructors to specify a content-type. See the source for the possible constructors in the nightly version of spray.

Also if you use spray-routing, you can leave marshalling/unmarshalling to the infrastructure.

Solution 3

In recent version of Spray (1.2.4 / 1.3.4), you may want to use respondWithMediaType. Here is the sample from the documentation :

val route =
  path("foo") {
    respondWithMediaType(`application/json`) {
      complete("[]") // marshalled to `text/plain` here
    }
  }

Note that while this overrides the HTTP header value, it will not override the marshaller used for serializing your content to the wire.

Therefore using a recent spray with spray routing, the original code would look like :

def receive = runRoute {
  path("/something") {
    get {
      respondWithMediaType(`application/json`) {
        complete("""{ "key": "value" }""")
      }
    }
  }
}

Solution 4

To add to 4lex1v's answer, there is a very nice, short, simple, working (as of 4/15, scala 2.11.5) tutorial on the GeoTrellis site, including a build.sbt. The GeoTrellis pieces are also straightforward to eliminate for the purposes of this stack overflow question.

http://geotrellis.io/tutorials/webservice/spray/

Share:
12,294
Jas
Author by

Jas

Updated on July 23, 2022

Comments

  • Jas
    Jas almost 2 years

    I understand that spray does that for me, but I still want to override it with my header, how can I override the header in the response?

    My response looks like this:

    case HttpRequest(GET, Uri.Path("/something"), _, _, _) =>
      sender ! HttpResponse(entity = """{ "key": "value" }""" // here i want to specify also response header i would like to explicitly set it and not get it implicitly
    
  • Jas
    Jas over 10 years
    I added the imports but i get not found: value runRoute def receive = runRoute { ^
  • 4lex1v
    4lex1v over 10 years
    @Tomer to have it you need to extend Actor with HttpService or just extends HttpServiceActor from spray routing package
  • Jas
    Jas over 10 years
    in the last example is it supposed also to work on a servlet container?
  • 4lex1v
    4lex1v over 10 years
    @Tomer You can, as i know, but i've never tried with servlets, i'm using spray-can and akka.
  • 4lex1v
    4lex1v over 10 years
    @Tomer i've added a little example of one project which is running on top of akka + spray-can