Skip to content

Commit

Permalink
decode_body: Do not decode response with content-encoding header
Browse files Browse the repository at this point in the history
  • Loading branch information
wojtekmach committed Aug 27, 2023
1 parent 315666f commit 0003caa
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 37 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ resp.body

* [`decompress_body`]: Remove `content-encoding` header after decompression

* [`decode_body`]: Do not decode resposne with `content-encoding` header

* [`run_finch`]: Add `:inet6` option

* [`retry`]: Support `retry: :safe_transient` which retries HTTP 408/429/500/502/503/504
Expand Down
3 changes: 2 additions & 1 deletion lib/req/steps.ex
Original file line number Diff line number Diff line change
Expand Up @@ -1256,7 +1256,8 @@ defmodule Req.Steps do
def decode_body({request, response}) do
if request.options[:raw] == true or
request.options[:decode_body] == false or
request.options[:output] do
request.options[:output] not in [nil, false] or
Req.Response.get_header(response, "content-encoding") != [] do
{request, response}
else
decode_body({request, response}, format(request, response))
Expand Down
99 changes: 63 additions & 36 deletions test/req/steps_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,45 @@ defmodule Req.StepsTest do
|> Plug.Conn.send_resp(200, :zlib.gzip("foo"))
end)

assert Req.get!(c.url).body == "foo"
resp = Req.get!(c.url)
assert Req.Response.get_header(resp, "content-encoding") == []
assert resp.body == "foo"
end

test "identity", c do
Bypass.expect(c.bypass, "GET", "/", fn conn ->
conn
|> Plug.Conn.put_resp_header("content-encoding", "identity")
|> Plug.Conn.send_resp(200, "foo")
end)

resp = Req.get!(c.url)
assert Req.Response.get_header(resp, "content-encoding") == []
assert resp.body == "foo"
end

test "brotli", c do
Bypass.expect(c.bypass, "GET", "/", fn conn ->
{:ok, body} = :brotli.encode("foo")

conn
|> Plug.Conn.put_resp_header("content-encoding", "br")
|> Plug.Conn.send_resp(200, body)
end)

resp = Req.get!(c.url)
assert resp.body == "foo"
end

test "zstd", c do
Bypass.expect(c.bypass, "GET", "/", fn conn ->
conn
|> Plug.Conn.put_resp_header("content-encoding", "zstd")
|> Plug.Conn.send_resp(200, :ezstd.compress("foo"))
end)

resp = Req.get!(c.url)
assert resp.body == "foo"
end

test "multiple codecs", c do
Expand All @@ -292,7 +330,9 @@ defmodule Req.StepsTest do
|> Plug.Conn.send_resp(200, "foo" |> :zlib.gzip() |> :ezstd.compress())
end)

assert Req.get!(c.url).body == "foo"
resp = Req.get!(c.url)
assert Req.Response.get_header(resp, "content-encoding") == []
assert resp.body == "foo"
end

test "multiple codecs with multiple headers" do
Expand All @@ -317,29 +357,9 @@ defmodule Req.StepsTest do
:ok = :gen_tcp.send(socket, data)
end)

assert Req.get!("http://localhost:#{port}").body == "foo"
end

test "brotli", c do
Bypass.expect(c.bypass, "GET", "/", fn conn ->
{:ok, body} = :brotli.encode("foo")

conn
|> Plug.Conn.put_resp_header("content-encoding", "br")
|> Plug.Conn.send_resp(200, body)
end)

assert Req.get!(c.url).body == "foo"
end

test "zstd", c do
Bypass.expect(c.bypass, "GET", "/", fn conn ->
conn
|> Plug.Conn.put_resp_header("content-encoding", "zstd")
|> Plug.Conn.send_resp(200, :ezstd.compress("foo"))
end)

assert Req.get!(c.url).body == "foo"
resp = Req.get!("http://localhost:#{port}")
assert Req.Response.get_header(resp, "content-encoding") == []
assert resp.body == "foo"
end

@tag :capture_log
Expand Down Expand Up @@ -382,17 +402,6 @@ defmodule Req.StepsTest do
[content_length] = Req.Response.get_header(resp, "content-length")
assert String.to_integer(content_length) == byte_size(body)
end

test "delete content-encoding header", c do
Bypass.expect(c.bypass, "GET", "/", fn conn ->
conn
|> Plug.Conn.put_resp_header("content-encoding", "x-gzip")
|> Plug.Conn.send_resp(200, :zlib.gzip("foo"))
end)

resp = Req.get!(c.url)
assert [] = Req.Response.get_header(resp, "content-encoding")
end
end

describe "output" do
Expand Down Expand Up @@ -623,6 +632,24 @@ defmodule Req.StepsTest do
}
end

test "decode with unknown compression codec" do
plug = fn conn ->
body =
%{a: 1}
|> Jason.encode_to_iodata!()
|> :zlib.compress()

conn
|> Plug.Conn.put_resp_header("content-encoding", "deflate")
|> Plug.Conn.put_resp_content_type("application/json")
|> Plug.Conn.send_resp(200, body)
end

assert Req.get!("", plug: plug).body |> :zlib.uncompress() |> Jason.decode!() == %{
"a" => 1
}
end

describe "redirect" do
test "absolute", c do
Bypass.expect(c.bypass, "GET", "/redirect", fn conn ->
Expand Down

0 comments on commit 0003caa

Please sign in to comment.