akka / akka/akka-http

Corresponding coding directives fail to process gzip- and deflate-compressed HTTP/1.0 requests

Open
#46 7 comments 0 reactions 0 assignees View on GitHub
1 - triaged discuss help wanted
Dominant language
Scala
Stars
1.4k
Forks
584
Avg merge
14h 33m
Merged PRs (30d)
24

Description

**Issue by [levkhomich](https://github.com/levkhomich)**
_Saturday Jul 16, 2016 at 06:40 GMT_
_Originally opened as https://github.com/akka/akka/issues/20969_

---

The problem is that `decodeRequest` and `decodeRequestWith` directives map original request entity to `HttpEntity.Chunked` which, in turn, fails `HttpRequest.copy`'s requirement

``` scala
require(
protocol == HttpProtocols.`HTTP/1.1` || !entity.isInstanceOf[HttpEntity.Chunked],
"HTTP/1.0 responses must not have a chunked entity")
```

and produces following stack trace:

```
java.lang.IllegalArgumentException: requirement failed: HTTP/1.0 requests must not have a chunked entity
at scala.Predef$.require(Predef.scala:224)
at akka.http.scaladsl.model.HttpRequest.(HttpMessage.scala:207)
at akka.http.scaladsl.model.HttpRequest.copy(HttpMessage.scala:271)
at akka.http.scaladsl.coding.DataMapper$$anonfun$1.apply(DataMapper.scala:32)
at akka.http.scaladsl.coding.DataMapper$$anonfun$1.apply(DataMapper.scala:28)
at akka.http.scaladsl.coding.DataMapper$$anon$3.transformDataBytes(DataMapper.scala:41)
at akka.http.scaladsl.coding.Decoder$class.decodeData(Decoder.scala:25)
at akka.http.scaladsl.coding.StreamDecoder$$anon$1.decodeData(Decoder.scala:44)
at akka.http.scaladsl.coding.Decoder$class.decode(Decoder.scala:22)
at akka.http.scaladsl.coding.StreamDecoder$$anon$1.decode(Decoder.scala:44)
at akka.http.scaladsl.server.directives.CodingDirectives$$anonfun$applyDecoder$1$1$$anonfun$apply$2.apply(CodingDirectives.scala:86)
at akka.http.scaladsl.server.directives.CodingDirectives$$anonfun$applyDecoder$1$1$$anonfun$apply$2.apply(CodingDirectives.scala:85)
```

Steps to reproduce. Test case:

``` scala
val echoRequestContent: Route = { ctx ⇒ ctx.complete(ctx.request.entity.dataBytes.utf8String) }
lazy val helloGzipped = compress("Hello", Gzip)
def compress(input: String, encoder: Encoder): ByteString = {
val compressor = encoder.newCompressor
compressor.compressAndFlush(ByteString(input)) ++ compressor.finish()
}

"decode HTTP/1.0 request with 'gzip' encoding" in {
HttpRequest(POST, Uri("/"), entity = HttpEntity(helloGzipped), protocol = `HTTP/1.0`) ~> `Content-Encoding`(gzip) ~> {
decodeRequestWith(Gzip) { echoRequestContent }
} ~> check { responseAs[String] shouldEqual "Hello" }
}
```

Contributor guide

Open the contributing guide

Research direction

Start with DataMapper.scala and CodingDirectives.scala, then inspect the HttpRequest requirement in HttpMessage.scala. Run the supplied HTTP/1.0 gzip reproduction and add or adapt coverage for deflate as well. Done means decodeRequest and decodeRequestWith process both compressed request types without the chunked-entity failure.

Written by the indexing model from the issue text.

Assessment

Tech stack
scala
Domain
api
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.