问题
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
回答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)
}
回答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.
回答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" }""")
}
}
}
}
回答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/
来源:https://stackoverflow.com/questions/19396187/how-do-i-specify-spray-content-type-response-header