=htc don't encode known to be empty entities (#21393) (#21396)

* =htc don't encode known to be empty entities (#21393)

* =htc added missing headers in the improved marshaller (#21393)
This commit is contained in:
gosubpl 2016-09-13 14:32:02 +02:00 committed by Konrad Malawski
parent ec50bd1441
commit 9b73fefdce
4 changed files with 47 additions and 2 deletions

View file

@ -47,6 +47,14 @@ class MarshallingSpec extends FreeSpec with Matchers with BeforeAndAfterAll with
marshalToResponse(StatusCodes.EnhanceYourCalm) shouldEqual
HttpResponse(StatusCodes.EnhanceYourCalm, entity = HttpEntity(StatusCodes.EnhanceYourCalm.defaultMessage))
}
"fromStatusCodeAndHeadersAndValue should properly marshal entities that are not supposed to have a body" in {
marshalToResponse((StatusCodes.NoContent, "This Content was intentionally left blank.")) shouldEqual
HttpResponse(StatusCodes.NoContent, entity = HttpEntity.Empty)
}
"fromStatusCodeAndHeadersAndValue should properly marshal entities that contain pre-defined content" in {
marshalToResponse((StatusCodes.EnhanceYourCalm, "Patience, young padawan!")) shouldEqual
HttpResponse(StatusCodes.EnhanceYourCalm, entity = HttpEntity("Patience, young padawan!"))
}
}
"The GenericMarshallers" - {

View file

@ -176,6 +176,29 @@ class CodingDirectivesSpec extends RoutingSpec with Inside {
encodeResponseWith(Deflate) { nope }
} ~> check { strictify(responseEntity) shouldEqual HttpEntity(ContentType(`text/plain`, `UTF-8`), nopeDeflated) }
}
"not encode the response content with GZIP if the response is of status not allowing entity" in {
Post() ~> {
encodeResponseWith(Gzip) { complete { StatusCodes.NoContent } }
} ~> check {
response should haveNoContentEncoding
response shouldEqual HttpResponse(StatusCodes.NoContent, entity = HttpEntity.Empty)
}
}
"not encode the response content with Deflate if the response is of status not allowing entity" in {
Post() ~> {
encodeResponseWith(Deflate) { complete((100, "Let's continue!")) }
} ~> check {
response should haveNoContentEncoding
response shouldEqual HttpResponse(StatusCodes.Continue, entity = HttpEntity.Empty)
}
}
"encode the response content with GZIP if the response is of status allowing entity" in {
Post() ~> {
encodeResponseWith(Gzip) { nope }
} ~> check {
response should haveContentEncoding(gzip)
}
}
}
"the Gzip encoder" should {

View file

@ -43,7 +43,10 @@ trait Encoder {
}
object Encoder {
val DefaultFilter: HttpMessage Boolean = isCompressible _
val DefaultFilter: HttpMessage Boolean = {
case req: HttpRequest isCompressible(req)
case res @ HttpResponse(status, _, _, _) isCompressible(res) && status.allowsEntity
}
private[coding] def isCompressible(msg: HttpMessage): Boolean =
msg.entity.contentType.mediaType.isCompressible

View file

@ -37,6 +37,16 @@ trait PredefinedToResponseMarshallers extends LowPriorityToResponseMarshallerImp
HttpResponse(status, entity = responseEntity)
}
implicit val fromStatusCodeAndHeaders: TRM[(StatusCode, immutable.Seq[HttpHeader])] =
Marshaller.withOpenCharset(`text/plain`) { (statusAndHeaders, charset)
val status = statusAndHeaders._1
val headers = statusAndHeaders._2
val responseEntity =
if (status.allowsEntity) HttpEntity(status.defaultMessage)
else HttpEntity.Empty
HttpResponse(status, headers, entity = responseEntity)
}
implicit def fromStatusCodeAndValue[S, T](implicit sConv: S StatusCode, mt: ToEntityMarshaller[T]): TRM[(S, T)] =
fromStatusCodeAndHeadersAndValue[T] compose { case (status, value) (sConv(status), Nil, value) }
@ -47,7 +57,8 @@ trait PredefinedToResponseMarshallers extends LowPriorityToResponseMarshallerImp
implicit def fromStatusCodeAndHeadersAndValue[T](implicit mt: ToEntityMarshaller[T]): TRM[(StatusCode, immutable.Seq[HttpHeader], T)] =
Marshaller(implicit ec {
case (status, headers, value) mt(value).fast map (_ map (_ map (HttpResponse(status, headers, _))))
case (status, headers, value) if (status.allowsEntity) mt(value).fast map (_ map (_ map (HttpResponse(status, headers, _))))
case (status, headers, _) fromStatusCodeAndHeaders((status, headers))
})
implicit def fromEntityStreamingSupportAndByteStringMarshaller[T, M](implicit s: EntityStreamingSupport, m: ToByteStringMarshaller[T]): ToResponseMarshaller[Source[T, M]] = {