Skip to content

Commit 35ebd6c

Browse files
authored
Revert "fix: return raw bytes from S3 and AzureBlob downloads (#26)" (#29)
This reverts commit f93e6b6.
1 parent f93e6b6 commit 35ebd6c

5 files changed

Lines changed: 6 additions & 92 deletions

File tree

lib/ash_storage/service.ex

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,10 @@ defmodule AshStorage.Service do
4343
@doc """
4444
Download a file from the storage service.
4545
46-
By default, services built on `Req` (S3, AzureBlob) run Req's `decode_body`
47-
step, so the returned body reflects the stored object's `content-type` —
48-
`application/json` comes back as a decoded map, `text/csv` as parsed rows,
49-
`application/zip` already unzipped, and so on. File-based services (Disk,
50-
Mirror) always return raw bytes.
51-
52-
Callers that need the exact uploaded bytes — writing to disk, streaming to
53-
a client, verifying a checksum — should pass `decode_body: false` via the
54-
service options on the `Req`-based services.
46+
Returns the file contents as binary data.
5547
"""
5648
@callback download(key(), Context.t()) ::
57-
{:ok, term()} | {:error, term()}
49+
{:ok, binary()} | {:error, term()}
5850

5951
@doc """
6052
Delete a file from the storage service.

lib/ash_storage/service/azure_blob.ex

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,6 @@ if Code.ensure_loaded?(Req) do
4949
(default: `"2020-12-06"`)
5050
- `:signed_protocol` - SAS protocol restriction. Defaults to `"https"`, or
5151
`"https,http"` for `http://` endpoints
52-
- `:decode_body` - whether `download/2` runs Req's content-type response
53-
decoding (JSON → map, CSV → rows, gzip → unzipped, etc.). Defaults to
54-
`true` to match Req's own default; pass `false` when you need the raw
55-
uploaded bytes.
5652
5753
## Azure setup
5854
@@ -113,8 +109,7 @@ if Code.ensure_loaded?(Req) do
113109
expires_in: [type: :integer],
114110
direct_upload_expires_in: [type: :integer],
115111
service_version: [type: :string],
116-
signed_protocol: [type: :string],
117-
decode_body: [type: :boolean]
112+
signed_protocol: [type: :string]
118113
]
119114
end
120115

@@ -153,11 +148,8 @@ if Code.ensure_loaded?(Req) do
153148
def download(key, %AshStorage.Service.Context{} = ctx) do
154149
full_key = prefixed_key(key, ctx)
155150

156-
decode_body? = Keyword.get(ctx.service_opts, :decode_body, true)
157-
158151
with {:ok, url} <- signed_blob_url(full_key, ctx, permissions: "r", expires_in: 900),
159-
{:ok, %{status: 200, body: body}} <-
160-
Req.get(url, headers: base_headers(ctx), decode_body: decode_body?),
152+
{:ok, %{status: 200, body: body}} <- Req.get(url, headers: base_headers(ctx)),
161153
:ok <- verify_md5(body, ctx.expected_md5) do
162154
{:ok, body}
163155
else

lib/ash_storage/service/s3.ex

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,6 @@ if Code.ensure_loaded?(ReqS3) do
2323
- `:secret_access_key` - AWS secret access key (falls back to `AWS_SECRET_ACCESS_KEY` env var)
2424
- `:endpoint_url` - custom endpoint URL for S3-compatible services (e.g. MinIO, Tigris)
2525
- `:prefix` - optional key prefix (e.g. `"uploads/"`)
26-
- `:decode_body` - whether `download/2` runs Req's content-type response
27-
decoding (JSON → map, CSV → rows, gzip → unzipped, etc.). Defaults to
28-
`true` to match Req's own default; pass `false` when you need the raw
29-
uploaded bytes.
3026
"""
3127

3228
@behaviour AshStorage.Service
@@ -39,8 +35,7 @@ if Code.ensure_loaded?(ReqS3) do
3935
access_key_id: [type: :string],
4036
secret_access_key: [type: :string],
4137
endpoint_url: [type: :string],
42-
prefix: [type: :string],
43-
decode_body: [type: :boolean]
38+
prefix: [type: :string]
4439
]
4540
end
4641

@@ -64,10 +59,7 @@ if Code.ensure_loaded?(ReqS3) do
6459
def download(key, %AshStorage.Service.Context{} = ctx) do
6560
full_key = prefixed_key(key, ctx)
6661

67-
decode_body? = Keyword.get(ctx.service_opts, :decode_body, true)
68-
69-
with {:ok, %{status: 200, body: body}} <-
70-
Req.get(req(ctx), url: "/#{full_key}", decode_body: decode_body?),
62+
with {:ok, %{status: 200, body: body}} <- Req.get(req(ctx), url: "/#{full_key}"),
7163
:ok <- verify_md5(body, ctx.expected_md5) do
7264
{:ok, body}
7365
else

test/ash_storage/service/azure_blob_integration_test.exs

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -142,32 +142,6 @@ defmodule AshStorage.Service.AzureBlobIntegrationTest do
142142
assert {:error, :not_found} = AzureBlob.download(unique_key(), ctx())
143143
end
144144

145-
test "auto-decodes JSON bodies by default" do
146-
key = unique_key()
147-
json = ~s({"name":"Alice","score":95})
148-
149-
assert :ok = AzureBlob.upload(key, json, ctx(content_type: "application/json"))
150-
151-
assert {:ok, %{"name" => "Alice", "score" => 95}} =
152-
AzureBlob.download(key, ctx())
153-
end
154-
155-
test "decode_body: false returns raw CSV bytes" do
156-
key = unique_key()
157-
csv = "Name,Score\nAlice,95\nBob,87\n"
158-
159-
assert :ok = AzureBlob.upload(key, csv, ctx(content_type: "text/csv"))
160-
assert {:ok, ^csv} = AzureBlob.download(key, ctx(decode_body: false))
161-
end
162-
163-
test "decode_body: false returns raw JSON bytes" do
164-
key = unique_key()
165-
json = ~s({"name":"Alice","score":95})
166-
167-
assert :ok = AzureBlob.upload(key, json, ctx(content_type: "application/json"))
168-
assert {:ok, ^json} = AzureBlob.download(key, ctx(decode_body: false))
169-
end
170-
171145
test "accepts upload when ctx expected_md5 matches the body" do
172146
key = unique_key()
173147
data = "checksum-verified payload"

test/ash_storage/service/s3_integration_test.exs

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -88,24 +88,6 @@ defmodule AshStorage.Service.S3IntegrationTest do
8888
assert {:error, :not_found} = S3.download(unique_key(), ctx())
8989
end
9090

91-
test "auto-decodes JSON bodies by default" do
92-
key = unique_key()
93-
json = ~s({"name":"Alice","score":95})
94-
95-
:ok = raw_put_with_content_type(key, json, "application/json")
96-
97-
assert {:ok, %{"name" => "Alice", "score" => 95}} =
98-
S3.download(key, ctx())
99-
end
100-
101-
test "decode_body: false returns raw bytes for content-typed objects" do
102-
key = unique_key()
103-
csv = "Name,Score\nAlice,95\nBob,87\n"
104-
105-
:ok = raw_put_with_content_type(key, csv, "text/csv")
106-
assert {:ok, ^csv} = S3.download(key, ctx(decode_body: false))
107-
end
108-
10991
test "accepts upload when ctx expected_md5 matches the body" do
11092
key = unique_key()
11193
data = "checksum-verified payload"
@@ -379,24 +361,6 @@ defmodule AshStorage.Service.S3IntegrationTest do
379361

380362
# -- Helpers --
381363

382-
defp raw_put_with_content_type(key, body, content_type) do
383-
url = "#{@service_opts[:endpoint_url]}/#{@bucket}/#{key}"
384-
385-
{:ok, %{status: status}} =
386-
Req.put(url,
387-
body: body,
388-
headers: %{"content-type" => content_type},
389-
aws_sigv4: [
390-
service: :s3,
391-
region: @service_opts[:region],
392-
access_key_id: @service_opts[:access_key_id],
393-
secret_access_key: @service_opts[:secret_access_key]
394-
]
395-
)
396-
397-
if status in 200..299, do: :ok, else: {:error, status}
398-
end
399-
400364
defp unique_key do
401365
"test/#{System.unique_integer([:positive])}-#{:crypto.strong_rand_bytes(4) |> Base.encode16(case: :lower)}"
402366
end

0 commit comments

Comments
 (0)