ex_aws
ex_aws copied to clipboard
ExAws.Request.Url.normalize_path/1 breaks operations on S3 objects with slashes at start of key name
The function that normalizes paths for AWS operations will cause operations on S3 objects with a /
as their first character to fail.
Environment
- Elixir & Erlang versions (elixir --version):
Erlang/OTP 20 [erts-9.2.1] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Elixir 1.6.1 (compiled with OTP 20)
- ExAws version:
mix deps | grep ex_aws
* ex_aws 2.0.2 (Hex package) (mix)
locked at 2.0.2 (ex_aws) 8df2f96f
* ex_aws_s3 2.0.0 (Hex package) (mix)
locked at 2.0.0 (ex_aws_s3) 404e7951
- HTTP client version:
mix deps | grep hackney
* hackney 1.11.0 (Hex package) (rebar3)
locked at 1.11.0 (hackney) 4951ee01
Current behavior
I've got a bucket that a third-party technology populated with objects whose keys begin with a /
:
(I've added two debug logs to the normalize_path/1
function to see the URL before and after it transforms it)
object = ExAws.S3.list_objects(bucket_name)
|> ExAws.stream!(connection_list)
|> Enum.take(2)
|> List.first
10:00:36.915 [debug] url before normalization: /mybucket//
10:00:36.915 [debug] url after normalization: /mybucket/
10:00:36.947 [debug] Request URL: "https://myendpoint/mybucket/"
...
%{
e_tag: "\"b0c2828fe6695df01c30df818c443cc8\"",
key: "/example/container/1234/12345",
last_modified: "2018-01-26T17:08:27.064Z",
owner: %{display_name: "example", id: "9ef748b4-b30e-7472-1190-5352fc03bf50"},
size: "104448",
storage_class: "STANDARD"
}
If I attempt to head one of these objects, it returns a 404 because the extra slash at the beginning of the object key is stripped off by normalize_path/1
ExAws.S3.head_object(bucket_name, object)
|> ExAws.request(connection_list)
10:00:41.666 [debug] url before normalization: /mybucket//example/container/1234/12345
10:00:41.666 [debug] url after normalization: /mybucket/example/container/1234/12345
10:00:41.666 [debug] Request URL: "https://myendpoint/mybucket/example/container/1234/12345"
...
10:00:41.666 [debug] Request BODY: ""
{:error,
{:http_error, 404,
%{
headers: [...],
status_code: 404
}}}
Workaround
Changing the normalize_path/1
function defp to:
defp normalize_path(url) do
url |> Map.update(:path, "", &String.replace(&1, ~r/\/{2,}$/, "/"))
end
This allows bucket listing (which needs the trailing /
stripped) to continue to work and also allows objects with and without the prepended /
on the key to be operated on.
Note
I'm near certain that I'm blind to a use case that requires stripping a number of slashes out of it, else this would have been a PR. Thought I'd kick off a dialog and see what shakes out.
Thanks for all the work you've done on ex_aws!