=htc simplify content negotiation

This commit is contained in:
2beaucoup 2014-12-10 10:56:38 +01:00 committed by André Rüdiger
parent d5d8c21091
commit a1d7c33663

View file

@ -43,32 +43,27 @@ class Marshal[A](val value: A) {
def qValueCS(charset: HttpCharset) = request.qValueForCharset(charset, charsetRanges)
m(value).fast.map { marshallings
def weight(mt: MediaType, cs: HttpCharset): Float = math.min(qValueMT(mt), qValueCS(cs))
val defaultMarshallingWeight: MarshallingWeight =
new MarshallingWeight(0f, { ()
val supportedContentTypes = marshallings collect {
case Marshalling.WithFixedCharset(mt, cs, _) ContentType(mt, cs)
case Marshalling.WithOpenCharset(mt, _) ContentType(mt)
}
throw UnacceptableResponseContentTypeException(supportedContentTypes.toSet)
})
val defaultMarshallingWeight = new MarshallingWeight(0f, { ()
val supportedContentTypes = marshallings collect {
case Marshalling.WithFixedCharset(mt, cs, _) ContentType(mt, cs)
case Marshalling.WithOpenCharset(mt, _) ContentType(mt)
}
throw UnacceptableResponseContentTypeException(supportedContentTypes.toSet)
})
def choose(acc: MarshallingWeight, mt: MediaType, cs: HttpCharset, marshal: () HttpResponse) = {
val weight = math.min(qValueMT(mt), qValueCS(cs))
if (weight > acc.weight) new MarshallingWeight(weight, marshal) else acc
}
val best = marshallings.foldLeft(defaultMarshallingWeight) {
case (acc, Marshalling.WithFixedCharset(mt, cs, marshal))
val w = weight(mt, cs)
if (w > acc.weight) new MarshallingWeight(w, marshal) else acc
choose(acc, mt, cs, marshal)
case (acc, Marshalling.WithOpenCharset(mt, marshal))
def withCharset(cs: HttpCharset) = {
val w = weight(mt, cs)
if (w > acc.weight) new MarshallingWeight(w, () marshal(cs)) else acc
}
def withCharset(cs: HttpCharset) = choose(acc, mt, cs, () marshal(cs))
// logic for choosing the charset adapted from http://tools.ietf.org/html/rfc7231#section-5.3.3
if (qValueCS(`UTF-8`) == 1f) withCharset(`UTF-8`) // prefer UTF-8 if fully accepted
else charsetRanges match { // ranges are sorted by descending q-value,
case (HttpCharsetRange.One(cs, qValue)) :: _ // so we only need to look at the first one
if (qValue == 1f) withCharset(cs) // if the client has high preference for this charset, pick it
else if (qValue > 0f) withCharset(cs) // ok, simply choose the first one if the client doesn't reject it
else acc
else charsetRanges match {
// pick the charset which the highest q-value (head of charsetRanges) if it isn't explicitly rejected
case (HttpCharsetRange.One(cs, qValue)) :: _ if qValue > 0f withCharset(cs)
case _ acc
}