我该如何指定喷射的Content-Type响应头?

9
我知道Spray可以替我完成这个任务,但我仍然想用我的头文件来覆盖它,我该如何在响应中覆盖头文件?
我的响应看起来像这样:
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

这是哪个版本的Spray? - jrudolph
4个回答

14

如果您仍然想要使用喷雾罐,则有两个选项,基于HttpResponse是一个case类。第一个选项是通过传递具有显式内容类型的List:

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`)))
  }

或者,第二种方法是使用withHeaders方法:
def receive = {
    case HttpRequest(GET, Uri.Path("/something"), _, _, _) =>
      val response: HttpResponse = HttpResponse(entity = """{ "key": "value" }""")
      sender ! response.withHeaders(List(`Content-Type`(`application/json`)))
  }

不过,就像jrudolph所说,在这种情况下最好使用 spray routing,这样看起来更好:

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

但是,使用Spray可以更加轻松,它会为您处理所有的(反)序列化工作:
import spray.httpx.SprayJsonSupport._
import spray.json.DefaultJsonProtocol._

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

在这种情况下,响应类型将由Spray自己设置为application/json

我的评论的完整示例:

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)
}

我已经添加了导入,但是出现了“not found: value runRoute”的错误。 def receive = runRoute { ^ - Jas
@Tomer 要使用它,你需要通过 spray routing 包中的 extend Actor with HttpService 或者 extends HttpServiceActor 来扩展 Actor。 - 4lex1v
在最后一个例子中,它是否也可以在Servlet容器上运行? - Jas
@Tomer,据我所知,你可以这样做,但我从未尝试过使用servlets,我正在使用spray-can和akka。 - 4lex1v
@Tomer 我已经添加了一个小例子,它是在 akka + spray-can 上运行的一个项目。 - 4lex1v

3
HttpResponseentity参数实际上是HttpEntity类型的,而你的字符串只是隐式地转换为HttpEntity的实例。你可以使用其他构造函数之一来指定内容类型。在spray的夜间版本中,可以查看源代码以获取可能的构造函数。

此外,如果您使用spray-routing,可以将编组/解组编码留给基础架构。


2

在最近版本的Spray(1.2.4 / 1.3.4)中,您可能希望使用respondWithMediaType。以下是文档中的示例

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

请注意,尽管这会覆盖HTTP头值,但它不会覆盖用于将内容序列化到线路的编组器。
因此,使用最新的spray和spray routing,原始代码应如下所示:
def receive = runRoute {
  path("/something") {
    get {
      respondWithMediaType(`application/json`) {
        complete("""{ "key": "value" }""")
      }
    }
  }
}

1
为了补充4lex1v的回答,GeoTrellis网站有一个非常好的、简短、简单、可行的教程(截至4/15,Scala 2.11.5),其中包括一个build.sbt。对于这个stackoverflow问题来说,也很容易消除GeoTrellis的组件。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接