From d082af4b196978d375f02f7ce9f72de9d2336498 Mon Sep 17 00:00:00 2001 From: Thales Macedo Garitezi Date: Tue, 21 May 2024 11:25:08 -0300 Subject: [PATCH 1/2] fix: allow specifying content type in `put_block_list` --- src/erlazure.erl | 13 +++++++++++-- test/erlazure_SUITE.erl | 22 +++++++++++++++------- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/erlazure.erl b/src/erlazure.erl index d1a6855..55857f8 100644 --- a/src/erlazure.erl +++ b/src/erlazure.erl @@ -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), @@ -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 %%==================================================================== diff --git a/test/erlazure_SUITE.erl b/test/erlazure_SUITE.erl index 9c4707d..604fba3 100644 --- a/test/erlazure_SUITE.erl +++ b/test/erlazure_SUITE.erl @@ -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. @@ -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. From 1b4242b3c1143b9999546a732a099a02938f5962 Mon Sep 17 00:00:00 2001 From: Thales Macedo Garitezi Date: Tue, 21 May 2024 11:30:33 -0300 Subject: [PATCH 2/2] chore: bump app vsn --- src/erlazure.app.src | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/erlazure.app.src b/src/erlazure.app.src index 4e35418..0da7949 100644 --- a/src/erlazure.app.src +++ b/src/erlazure.app.src @@ -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]},