Akka-http:接受并Content-type处理
Akka-http: Accept and Content-type handling
我正在尝试 Akka-http,希望有人能解答以下问题:
如何根据请求中的 accept: header 创建不同的路由?例如,我想要一个代码路径来处理 "json",一个代码路径来处理 "xml" 请求(如果缺少 header,则默认为 "json")
如果我不想推断出 contentType,我该如何指定它?例如,在下面的代码中,我尝试通过 compactPrint() 运行 json 但这会将其更改为字符串,因此 "text/plain"。我想覆盖它并告诉客户它仍然是 json。
我的代码是这样的;
...
path("api") {
get {
complete {
getStuff.map[ToResponseMarshallable] {
case Right(r) if r.isEmpty => List[String]().toJson.compactPrint
case Right(r) => r.toJson.compactPrint
case Left(e) => BadRequest -> e
}
}
}
}
...
本例中的响应是 text/plain,因为 compactPrint 创建了一个字符串。
非常欢迎批评。 ;)
您可以按如下方式定义内容类型,
complete {
HttpResponse(entity = HttpEntity(ContentType(MediaTypes.`application/json`), """{"id":"1"}"""))
}
您可以创建自定义指令,
def handleReq(json: String) = {
(get & extract(_.request.acceptedMediaRanges)) {
r =>
val encoding: MediaRange =
r.intersect(myEncodings).headOption
.getOrElse(MediaTypes.`application/json`)
complete {
// check conditions here
// HttpResponse(entity = HttpEntity(encoding.specimen, json)) //
}
}
}
并在路由中使用指令 as
val route = path("api"){ handleReq(json) }
问题 #1 的可能答案似乎是这样,但我想通过自定义指令或更优雅的方式来完成。不幸的是,似乎缺少 Akka-Http 自定义指令的文档。
// the encodings I want, in the order of preference
val myEncodings = Seq(MediaRange(`application/xml`),MediaRange( `application/json`))
...
path("api") {
(get & extract(_.request.acceptedMediaRanges)){
r =>
val encoding =
r.intersect(myEncodings).headOption
.getOrElse(MediaRange(`application/json`))
complete {
// check "encoding" here and make decision.
}
}
}
...
希望有人能提供更清洁的东西。
已接受的答案似乎不再适用于 akka-http v10.0.3。
这虽然有效:
// the encodings I want, in the order of preference
val myEncodings = Seq(MediaRange(`application/xml`),MediaRange( `application/json`))
...
path("api") {
(get & extract(_.request.headers)){ requestHeaders =>
val mediaTypeNegotiator = new MediaTypeNegotiator(requestHeaders)
val encoding = mediaTypeNegotiator
.acceptedMediaRanges
.intersect(myEncodings)
.headOption
.getOrElse(MediaRange(`application/json`))
complete {
// check "encoding" here and make decision.
}
}
}
...
你也可以
val myEncodings = Seq(MediaRange(`application/xml`),MediaRange( `application/json`))
path("api") {
(get & extract(_.request.headers)){ requestHeaders =>
complete {
val mediaTypeNegotiator = new MediaTypeNegotiator(requestHeaders)
if(mediaTypeNegotiator.accept(MediaTypes.`application/xml`)) {
// respond with xml
} else if(mediaTypeNegotiator.accept(MediaTypes.`application/json`)) {
// respond with json
} else {
// respond with json by default or reject properly :
reject(UnsupportedRequestContentTypeRejection(Set(MediaTypes.`application/xml`, MediaTypes.`application/json`)))
}
}
}
}
希望对您有所帮助。
我正在尝试 Akka-http,希望有人能解答以下问题:
如何根据请求中的 accept: header 创建不同的路由?例如,我想要一个代码路径来处理 "json",一个代码路径来处理 "xml" 请求(如果缺少 header,则默认为 "json")
如果我不想推断出 contentType,我该如何指定它?例如,在下面的代码中,我尝试通过 compactPrint() 运行 json 但这会将其更改为字符串,因此 "text/plain"。我想覆盖它并告诉客户它仍然是 json。
我的代码是这样的;
...
path("api") {
get {
complete {
getStuff.map[ToResponseMarshallable] {
case Right(r) if r.isEmpty => List[String]().toJson.compactPrint
case Right(r) => r.toJson.compactPrint
case Left(e) => BadRequest -> e
}
}
}
}
...
本例中的响应是 text/plain,因为 compactPrint 创建了一个字符串。 非常欢迎批评。 ;)
您可以按如下方式定义内容类型,
complete {
HttpResponse(entity = HttpEntity(ContentType(MediaTypes.`application/json`), """{"id":"1"}"""))
}
您可以创建自定义指令,
def handleReq(json: String) = {
(get & extract(_.request.acceptedMediaRanges)) {
r =>
val encoding: MediaRange =
r.intersect(myEncodings).headOption
.getOrElse(MediaTypes.`application/json`)
complete {
// check conditions here
// HttpResponse(entity = HttpEntity(encoding.specimen, json)) //
}
}
}
并在路由中使用指令 as
val route = path("api"){ handleReq(json) }
问题 #1 的可能答案似乎是这样,但我想通过自定义指令或更优雅的方式来完成。不幸的是,似乎缺少 Akka-Http 自定义指令的文档。
// the encodings I want, in the order of preference
val myEncodings = Seq(MediaRange(`application/xml`),MediaRange( `application/json`))
...
path("api") {
(get & extract(_.request.acceptedMediaRanges)){
r =>
val encoding =
r.intersect(myEncodings).headOption
.getOrElse(MediaRange(`application/json`))
complete {
// check "encoding" here and make decision.
}
}
}
...
希望有人能提供更清洁的东西。
已接受的答案似乎不再适用于 akka-http v10.0.3。
这虽然有效:
// the encodings I want, in the order of preference
val myEncodings = Seq(MediaRange(`application/xml`),MediaRange( `application/json`))
...
path("api") {
(get & extract(_.request.headers)){ requestHeaders =>
val mediaTypeNegotiator = new MediaTypeNegotiator(requestHeaders)
val encoding = mediaTypeNegotiator
.acceptedMediaRanges
.intersect(myEncodings)
.headOption
.getOrElse(MediaRange(`application/json`))
complete {
// check "encoding" here and make decision.
}
}
}
...
你也可以
val myEncodings = Seq(MediaRange(`application/xml`),MediaRange( `application/json`))
path("api") {
(get & extract(_.request.headers)){ requestHeaders =>
complete {
val mediaTypeNegotiator = new MediaTypeNegotiator(requestHeaders)
if(mediaTypeNegotiator.accept(MediaTypes.`application/xml`)) {
// respond with xml
} else if(mediaTypeNegotiator.accept(MediaTypes.`application/json`)) {
// respond with json
} else {
// respond with json by default or reject properly :
reject(UnsupportedRequestContentTypeRejection(Set(MediaTypes.`application/xml`, MediaTypes.`application/json`)))
}
}
}
}
希望对您有所帮助。