Skip to content

Commit a8e2184

Browse files
authored
Merge pull request #33 from testdouble/support-additional-headers
Support additional headers
2 parents 3f49170 + ba8f1c4 commit a8e2184

File tree

3 files changed

+62
-15
lines changed

3 files changed

+62
-15
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
## [Unreleased]
22

3+
- Add support for additional headers to all endpoints
34
- Fix typo in class name `AzureBlob::ForbidenError` to `AzureBlob::ForbiddenError`
45
- Fix proper URI encoding for keys with special characters like question marks
56

lib/azure_blob/client.rb

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def get_blob(key, options = {})
7272

7373
headers = {
7474
"x-ms-range": options[:start] && "bytes=#{options[:start]}-#{options[:end]}",
75-
}
75+
}.merge(additional_headers(options))
7676

7777
Http.new(uri, headers, signer:).get
7878
end
@@ -97,7 +97,7 @@ def copy_blob(key, source_key, options = {})
9797
headers = {
9898
"x-ms-copy-source": source_uri.to_s,
9999
"x-ms-requires-sync": "true",
100-
}
100+
}.merge(additional_headers(options))
101101

102102
Http.new(uri, headers, signer:, **options.slice(:metadata, :tags)).put
103103
end
@@ -116,7 +116,7 @@ def delete_blob(key, options = {})
116116

117117
headers = {
118118
"x-ms-delete-snapshots": options[:delete_snapshots] || "include",
119-
}
119+
}.merge(additional_headers(options))
120120

121121
Http.new(uri, headers, signer:).delete
122122
end
@@ -157,7 +157,7 @@ def list_blobs(options = {})
157157
query[:marker] = marker
158158
query.reject! { |key, value| value.to_s.empty? }
159159
uri.query = URI.encode_www_form(**query)
160-
response = Http.new(uri, signer:).get
160+
response = Http.new(uri, additional_headers(options), signer:).get
161161
end
162162

163163
BlobList.new(fetcher)
@@ -172,7 +172,7 @@ def list_blobs(options = {})
172172
def get_blob_properties(key, options = {})
173173
uri = generate_uri("#{container}/#{key}")
174174

175-
response = Http.new(uri, signer:).head
175+
response = Http.new(uri, additional_headers(options), signer:).head
176176

177177
Blob.new(response)
178178
end
@@ -193,10 +193,10 @@ def blob_exist?(key, options = {})
193193
# Takes a key (path) of the blob.
194194
#
195195
# Returns a hash of the blob's tags.
196-
def get_blob_tags(key)
196+
def get_blob_tags(key, options = {})
197197
uri = generate_uri("#{container}/#{key}")
198198
uri.query = URI.encode_www_form(comp: "tags")
199-
response = Http.new(uri, signer:).get
199+
response = Http.new(uri, additional_headers(options), signer:).get
200200

201201
Tags.from_response(response).to_h
202202
end
@@ -209,7 +209,7 @@ def get_blob_tags(key)
209209
def get_container_properties(options = {})
210210
uri = generate_uri(container)
211211
uri.query = URI.encode_www_form(restype: "container")
212-
response = Http.new(uri, signer:, raise_on_error: false).head
212+
response = Http.new(uri, additional_headers(options), signer:, raise_on_error: false).head
213213

214214
Container.new(response)
215215
end
@@ -229,6 +229,7 @@ def create_container(options = {})
229229
headers = {}
230230
headers[:"x-ms-blob-public-access"] = "blob" if options[:public_access]
231231
headers[:"x-ms-blob-public-access"] = options[:public_access] if [ "container", "blob" ].include?(options[:public_access])
232+
headers.merge!(additional_headers(options))
232233

233234
uri.query = URI.encode_www_form(restype: "container")
234235
response = Http.new(uri, headers, signer:).put
@@ -240,7 +241,7 @@ def create_container(options = {})
240241
def delete_container(options = {})
241242
uri = generate_uri(container)
242243
uri.query = URI.encode_www_form(restype: "container")
243-
response = Http.new(uri, signer:).delete
244+
response = Http.new(uri, additional_headers(options), signer:).delete
244245
end
245246

246247
# Return a URI object to a resource in the container. Takes a path.
@@ -284,7 +285,7 @@ def create_append_blob(key, options = {})
284285
"Content-Type": options[:content_type],
285286
"Content-MD5": options[:content_md5],
286287
"x-ms-blob-content-disposition": options[:content_disposition],
287-
}
288+
}.merge(additional_headers(options))
288289

289290
Http.new(uri, headers, signer:, **options.slice(:metadata, :tags)).put(nil)
290291
end
@@ -306,7 +307,7 @@ def append_blob_block(key, content, options = {})
306307
"Content-Length": content.size,
307308
"Content-Type": options[:content_type],
308309
"Content-MD5": options[:content_md5],
309-
}
310+
}.merge(additional_headers(options))
310311

311312
Http.new(uri, headers, signer:).put(content)
312313
end
@@ -330,7 +331,7 @@ def put_blob_block(key, index, content, options = {})
330331
"Content-Length": content.size,
331332
"Content-Type": options[:content_type],
332333
"Content-MD5": options[:content_md5],
333-
}
334+
}.merge(additional_headers(options))
334335

335336
Http.new(uri, headers, signer:).put(content)
336337

@@ -359,12 +360,17 @@ def commit_blob_blocks(key, block_ids, options = {})
359360
"Content-Type": options[:content_type],
360361
"x-ms-blob-content-md5": options[:content_md5],
361362
"x-ms-blob-content-disposition": options[:content_disposition],
362-
}
363+
}.merge(additional_headers(options))
363364

364365
Http.new(uri, headers, signer:, **options.slice(:metadata, :tags)).put(content)
365366
end
366367

367-
private
368+
private
369+
370+
def additional_headers(options)
371+
(options[:headers] || {}).transform_keys { |k| "x-ms-#{k}".to_sym }.
372+
transform_values(&:to_s)
373+
end
368374

369375
def generate_block_id(index)
370376
Base64.urlsafe_encode64(index.to_s.rjust(6, "0"))
@@ -391,7 +397,7 @@ def put_blob_single(key, content, options = {})
391397
"Content-Type": options[:content_type],
392398
"x-ms-blob-content-md5": options[:content_md5],
393399
"x-ms-blob-content-disposition": options[:content_disposition],
394-
}
400+
}.merge(additional_headers(options))
395401

396402
Http.new(uri, headers, signer:, **options.slice(:metadata, :tags)).put(content.read)
397403
end

test/client/test_client.rb

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,4 +433,44 @@ def test_copy_between_containers
433433
rescue AzureBlob::Http::FileNotFoundError
434434
end
435435
end
436+
437+
def test_get_blob_additional_headers
438+
http_mock = Minitest::Mock.new
439+
http_mock.expect :get, ""
440+
441+
stubbed_new = lambda do |uri, headers = {}, signer: nil, **kwargs|
442+
assert_equal "bar", headers[:"x-ms-foo"]
443+
http_mock
444+
end
445+
446+
AzureBlob::Http.stub :new, stubbed_new do
447+
custom_client = AzureBlob::Client.new(account_name: "foo", access_key: "bar", container: "cont")
448+
custom_client.get_blob(key, headers: { foo: "bar" })
449+
end
450+
451+
http_mock.verify
452+
dummy = Minitest::Mock.new
453+
dummy.expect :delete_blob, nil, [ key ]
454+
@client = dummy
455+
end
456+
457+
def test_create_append_blob_additional_headers
458+
http_mock = Minitest::Mock.new
459+
http_mock.expect :put, true, [ nil ]
460+
461+
stubbed_new = lambda do |uri, headers = {}, signer: nil, **kwargs|
462+
assert_equal "bar", headers[:"x-ms-foo"]
463+
http_mock
464+
end
465+
466+
AzureBlob::Http.stub :new, stubbed_new do
467+
custom_client = AzureBlob::Client.new(account_name: "foo", access_key: "bar", container: "cont")
468+
custom_client.create_append_blob(key, headers: { foo: "bar" })
469+
end
470+
471+
http_mock.verify
472+
dummy = Minitest::Mock.new
473+
dummy.expect :delete_blob, nil, [ key ]
474+
@client = dummy
475+
end
436476
end

0 commit comments

Comments
 (0)