9

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
  • 12,534
  • 20
  • 79
  • 134

4 Answers4

14

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)
}
Community
  • 1
  • 1
4lex1v
  • 20,667
  • 6
  • 48
  • 81
  • I added the imports but i get `not found: value runRoute def receive = runRoute { ^` – Jas Oct 16 '13 at 07:45
  • @Tomer to have it you need to `extend Actor with HttpService` or just `extends HttpServiceActor` from spray routing package – 4lex1v Oct 16 '13 at 07:48
  • in the last example is it supposed also to work on a servlet container? – Jas Oct 16 '13 at 08:14
  • @Tomer You can, as i know, but i've never tried with servlets, i'm using spray-can and akka. – 4lex1v Oct 16 '13 at 08:16
  • @Tomer i've added a little example of one project which is running on top of akka + spray-can – 4lex1v Oct 16 '13 at 08:21
3

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.

jrudolph
  • 7,987
  • 4
  • 29
  • 48
2

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" }""")
      }
    }
  }
}
Jean
  • 20,591
  • 5
  • 43
  • 61
1

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/

Ram Rajamony
  • 1,571
  • 13
  • 17