agemooij / riak-scala-client

An easy to use, non-blocking, fast Scala client library for interacting with Riak.
http://riak.scalapenos.com/
Apache License 2.0
84 stars 24 forks source link

[Compression] Riak may return a gzipped payload unexpectedly #42

Open ajantis opened 7 years ago

ajantis commented 7 years ago

Problem

The optional gzip compression for requests and responses is introduced with https://github.com/agemooij/riak-scala-client/pull/40 PR.

During the implementation, an interesting Riak compression-related behaviour was found: if a value was stored using gzipped request, then all subsequent 'fetch-value' requests are served with gzipped responses (no matter if requests don't specify an Accept-Encoding header).

Moreover, if a subsequent 'fetch-value' request does specify an Accept-Encoding: identity header (which is supposed to force a no-encoding option), Riak responds with a HTTP 406 Not Acceptable error. o_O

So, "if a value has been stored with a gzipped request, one should not dare to read it without compression support". <- "đź‘Ť"

alt text

How to reproduce

# Prepare a simple test gzipped payload
> echo “bar" | gzip > bar.gz

# Store a value with a compressed request
> curl -XPUT --data-binary @bar.gz -H "Content-Encoding: gzip" http://127.0.0.1:8098/buckets/test-client-compression-support/keys/foo

# Fetch a value with no `Accept-Encoding` header: response will be gzipped!
> curl -v http://127.0.0.1:8098/buckets/test-client-compression-support/keys/foo

… Content-Encoding: gzip …

# Try to fetch a value with a forced “no encoding” (i.e `Accept-Encoding: identity` header): a 406 Not Acceptable error is returned!
> curl -H "Accept-Encoding: identity" http://127.0.0.1:8098/buckets/test-client-compression-support/keys/foo 
<html><head><title>406 Not Acceptable</title></head><body><h1>Not Acceptable</h1>Not Acceptable<p><hr><address>mochiweb+webmachine web server</address></body></html>

This scenario is reproducible with eleveldb and memory backends, with Riak 1.4.10 and 2.1.1 versions.

Workaround

As a workaround, Riak response headers (both for normal AND multipart responses) are always inspected and payload is decoded if necessary (whether gzip encoding was requested or not). This workaround is tested with RiakGzipSpec specs.