How do i specify spray Content-Type response heade

2020-03-12 04:57发布

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

标签: scala akka spray
4条回答
Luminary・发光体
2楼-- · 2020-03-12 05:17

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" }""")
      }
    }
  }
}
查看更多
霸刀☆藐视天下
3楼-- · 2020-03-12 05:31

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.

查看更多
手持菜刀,她持情操
4楼-- · 2020-03-12 05:34

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)
}
查看更多
太酷不给撩
5楼-- · 2020-03-12 05:36

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/

查看更多
登录 后发表回答