Skip to content

Commit

Permalink
fix: allow specifying content type in put_block_list
Browse files Browse the repository at this point in the history
  • Loading branch information
thalesmg committed May 21, 2024
1 parent f74212a commit 438edf9
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 9 deletions.
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.

0 comments on commit 438edf9

Please sign in to comment.