Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document/disable OkHttp's automatic response decompression #1041

Closed
ianbotsf opened this issue Feb 22, 2024 · 2 comments · Fixed by #1047 or awslabs/aws-sdk-kotlin#1260
Closed

Document/disable OkHttp's automatic response decompression #1041

ianbotsf opened this issue Feb 22, 2024 · 2 comments · Fixed by #1047 or awslabs/aws-sdk-kotlin#1260
Assignees
Labels
bug This issue is a bug.

Comments

@ianbotsf
Copy link
Contributor

Describe the bug

Getting a compressed object from S3 with S3Client.getObject when using the default OkHttp engine returns the body uncompressed instead of in its original, persisted form. This is because OkHttp automatically accepts and decompresses GZipped responses. This behavior is surprising and differs from CRT engine and the Java v2 SDK, both of which return the compressed object body.

Expected Behavior

Users are not surprised by unexpectedly decompressed objects.

Steps to Reproduce

This code shows the issue:

val uncompressed = ByteArray(1024) { it.mod(Byte.MAX_VALUE) }
val compressed = ByteArrayOutputStream()
    .also { GZIPOutputStream(it, true).apply {
        write(uncompressed)
        flush()
        close()
    } }
    .toByteArray()
println("Uncompressed length: ${uncompressed.size}") // Uncompressed length: 1024
println("Compressed length: ${compressed.size}") // Compressed length: 164

runBlocking {
    S3Client.fromEnvironment().use { s3 ->
        s3.putObject {
            bucket = "<some-bucket>"
            key = "compression-test"
            contentEncoding = "gzip"
            body = ByteStream.fromBytes(compressed)
        }

        s3.getObject(GetObjectRequest {
            bucket = "<some-bucket>"
            key = "compression-test"
        }) {
            println("Response length: ${it.body?.toByteArray()?.size}") // Response length: 1024
        }
    }
}

Possible Solution

We should either:

  • document this behavior more clearly
  • offer HTTP engine settings to change it
  • disable the OkHttp transparent decompression altogether

Context

Currently available workarounds include setting responseContentEncoding = "identity" in the GetObjectRequest, adding an interceptor to accomplish the same thing, or using the CRT engine.

Your Environment

  • Smithy Kotlin version used: 1.0.15
  • Platform (JVM/JS/Native): OpenJDK 8
  • Operating System and version: Amazon Linux 2
@ianbotsf ianbotsf added the bug This issue is a bug. label Feb 22, 2024
@ianbotsf
Copy link
Contributor Author

After discussing this we consider this behavior incongruent with other HTTP engines and other AWS SDKs. Our best fix will be to disable transparent decompression altogether, likely by manually setting Accept-Encoding: identity when we construct the OkHttp request object.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug This issue is a bug.
Projects
None yet
2 participants