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

fix: allow specifying content type in put_block_list #10

Merged
merged 2 commits into from
May 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/erlazure.app.src
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{application, erlazure,
[{description, "Windows Azure Erlang bindings"},
{vsn, "0.3.0.1"},
{vsn, "0.3.0.2"},
{modules, []},
{registered, []},
{applications, [kernel, stdlib, crypto, inets, ssl]},
Expand Down
13 changes: 11 additions & 2 deletions src/erlazure.erl
Original file line number Diff line number Diff line change
Expand Up @@ -678,12 +678,13 @@ handle_call({put_block, Container, Blob, BlockId, Content, Options}, _From, Stat
return_response(Code, Body, State, ?http_created, created);

% Put block list
handle_call({put_block_list, Container, Blob, BlockRefs, Options}, _From, State) ->
handle_call({put_block_list, Container, Blob, BlockRefs, Options0}, _From, State) ->
ServiceContext = new_service_context(?blob_service, State),
{ExtraReqOpts, Options} = proplist_take(req_opts, Options0, []),
ReqOptions = [{method, put},
{path, lists:concat([Container, "/", Blob])},
{body, erlazure_blob:get_request_body(BlockRefs)},
{params, [{comp, "blocklist"}] ++ Options}],
{params, [{comp, "blocklist"}] ++ Options} | ExtraReqOpts],
ReqContext = new_req_context(?blob_service, ReqOptions, State),

{Code, Body} = execute_request(ServiceContext, ReqContext),
Expand Down Expand Up @@ -1085,6 +1086,14 @@ ensure_wrapped_key(#{key := Key} = InitOpts) ->
InitOpts#{key := wrap(Key)}
end.

proplist_take(Key, Proplist, Default) ->
case lists:keytake(Key, 1, Proplist) of
false ->
{Default, Proplist};
{value, {Key, Value}, NewProplist} ->
{Value, NewProplist}
end.

%%====================================================================
%% Tests
%%====================================================================
Expand Down
22 changes: 15 additions & 7 deletions test/erlazure_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -175,10 +175,10 @@ t_put_block(Config) ->
Container = container_name(?FUNCTION_NAME),
?assertMatch({[], _}, erlazure:list_containers(Pid)),
?assertMatch({ok, created}, erlazure:create_container(Pid, Container)),
%% Upload some blocks
Opts = [{content_type, "text/csv"}],
%% Upload some blocks. Note: this content-type will be overwritten later by `put_block_list'.
Opts1 = [{content_type, "application/json"}],
BlobName = "blob1",
?assertMatch({ok, created}, erlazure:put_block_blob(Pid, Container, BlobName, <<>>, Opts)),
?assertMatch({ok, created}, erlazure:put_block_blob(Pid, Container, BlobName, <<"0">>, Opts1)),
%% Note: this short name is important for this test. It'll produce a base64 string
%% that's padded. That padding must be URL-encoded when sending the request, but not
%% when generating the string to sign.
Expand All @@ -187,21 +187,29 @@ t_put_block(Config) ->
%% Testing iolists
BlockId2 = <<"blo2">>,
?assertMatch({ok, created}, erlazure:put_block(Pid, Container, BlobName, BlockId2, [<<"\n">>, ["b", [$\n]]])),
%% Not yet committed.
?assertMatch({ok, <<"">>}, erlazure:get_blob(Pid, Container, BlobName)),
%% Not yet committed. Contains only the data from the blob creation.
?assertMatch({ok, <<"0">>}, erlazure:get_blob(Pid, Container, BlobName)),
%% Committing
BlockList1 = [{BlockId1, latest}],
?assertMatch({ok, created}, erlazure:put_block_list(Pid, Container, BlobName, BlockList1)),
%% Committed only first block.
%% Committed only first block. Initial data was lost, as it was not in the block list.
?assertMatch({ok, <<"a">>}, erlazure:get_blob(Pid, Container, BlobName)),
%% Block 2 was dropped after committing.
?assertMatch({[#blob_block{id = "blo1"}], _}, erlazure:get_block_list(Pid, Container, BlobName)),
BlockId3 = <<"blo3">>,
?assertMatch({ok, created}, erlazure:put_block(Pid, Container, BlobName, BlockId3, [<<"\n">>, ["b", [$\n]]])),
%% Commit both blocks
Opts2 = [{req_opts, [{headers, [{"x-ms-blob-content-type", "text/csv"}]}]}],
BlockList2 = [{BlockId1, committed}, {BlockId3, uncommitted}],
?assertMatch({ok, created}, erlazure:put_block_list(Pid, Container, BlobName, BlockList2)),
?assertMatch({ok, created}, erlazure:put_block_list(Pid, Container, BlobName, BlockList2, Opts2)),
?assertMatch({ok, <<"a\nb\n">>}, erlazure:get_blob(Pid, Container, BlobName)),
%% Check content type.
ListedBlobs = erlazure:list_blobs(Pid, Container),
?assertMatch({[#cloud_blob{name = "blob1"}], _},
ListedBlobs),
{[#cloud_blob{name = "blob1", properties = Props}], _} = ListedBlobs,
%% Content-type from `put_block_list' prevails.
?assertMatch(#{content_type := "text/csv"}, maps:from_list(Props)),
%% Delete container
?assertMatch({ok, deleted}, erlazure:delete_container(Pid, Container)),
ok.