J'essaie Akka-http et j'espère que quelqu'un pourra faire la lumière sur les questions suivantes:
Comment créer des itinéraires différents en fonction de l'en-tête accept: de la demande? Par exemple, je veux un chemin de code pour gérer "json" et un pour gérer les requêtes "xml" (avec par défaut "json" si l'en-tête est manquant)
Dans les cas où je ne veux pas que le contentType soit déduit, comment puis-je le spécifier? Par exemple, dans le code ci-dessous, j'essaie d'exécuter le JSON via compactPrint (), mais cela le change en chaîne, d'où le libellé "text/plain". Je veux annuler cela et dire au client que c'est toujours JSON.
Mon code est quelque chose comme ça;
...
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
}
}
}
}
...
La réponse dans ce cas est text/plain, puisque compactPrint crée une chaîne . Critique très bienvenue. ;)
Vous pouvez définir le type de contenu comme suit,
complete {
HttpResponse(entity = HttpEntity(ContentType(MediaTypes.`application/json`), """{"id":"1"}"""))
}
Vous pouvez créer votre directive personnalisée en tant que,
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)) //
}
}
}
et utiliser la directive en route comme
val route = path("api"){ handleReq(json) }
La réponse possible à la question n ° 1 semble être la suivante, mais j'aimerais le faire via une directive personnalisée ou quelque chose de plus élégant. Malheureusement, la documentation relative aux directives personnalisées Akka-Http semble faire défaut.
// 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.
}
}
}
...
En espérant que quelqu'un puisse fournir quelque chose de plus propre.
Il semble que la réponse acceptée ne fonctionne plus avec akka-http v10.0.3.
Cela fonctionne bien:
// 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.
}
}
}
...
tu pourrais aussi faire
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`)))
}
}
}
}
J'espère que cela aide.