Do HTTP RANGE headers work with Azure Blob Storage Shared Access Signatures?
Asked Answered
C

5

10

I'm using Azure Blob Storage to store media files and providing access to these files using Shared Access Signatures; everything is working well in this regard.

However, I have a client application that needs to "resume" access to these files and does so using an HTTP RANGE header. When it makes a request like this, it is unhappy with the result it gets back from Azure.

I'm not sure how to view the details on the Azure side to see if the request failed, or if it just returned something the client didn't expect, and I have no debugging visibility into the client.

Here's what the incoming range header looks like:

RANGE: bytes=4258672-

From the Azure documentation I've read it appears to support RANGE headers, however I'm wondering if there is a conflict using RANGE and Shared Access Signatures together?

Update: It appears that Azure may be returning an incorrect status code for RANGE requests, which is causing my client apps to reject the response. The documentation states that Azure will respond with an HTTP status code of 206 when responding to a RANGE request, however when I issue a RANGE request like this:

curl -I -H "User-Agent: Bonos" -r 500- "https://murfie.blob.core.windows.net/168464/1.mp3?st=2013-07-03T16%3A34%3A32.4832235Z&se=2013-07-03T17%3A34%3A32.4613735Z&sr=b&sp=r&sig=mJgQGW%2Fr3v8HN2%2BVV3Uady7J68nFqeHyzQb37HAhfuE%3D"

Azure returns the following:

HTTP/1.1 200 OK
Content-Length: 19988911
Content-Type: application/octet-stream Charset=UTF-8
Last-Modified: Fri, 07 Jun 2013 16:44:50 GMT
ETag: 0x8D031B57670B986
Server: Blob Service Version 1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: 77312761-65a9-42ef-90cd-ff718a80b231
Date: Wed, 03 Jul 2013 16:41:01 GMT
Cusco answered 1/7, 2013 at 16:6 Comment(1)
For those who are curious about 2011-08-18: Version 2011-08-18 (REST API) - Azure Storage | Microsoft LearnGaziantep
C
10

We got this straightened out.

As @BrentDaCodeMonkey mentioned, Azure returns the expected 206 response if you're using API version 2011-01-18 or better, but in our case we don't originate the request so we can't specify this using the request header.

However, some Microsoft friends tipped us of to the fact that you can set the API version globally for a storage account, but you need to use the REST API to do so (it's not something you can do in the management UI). This post explains how:

http://msdn.microsoft.com/en-us/library/windowsazure/hh452235.aspx

After setting the DefaultServiceVersion to 2011-01-18, we're now getting back the expected 206 status for RANGE requests.

Cusco answered 18/7, 2013 at 14:57 Comment(3)
Just a head's up from a frustrated coder who spent nearly two days working through this same issue -- it should be version 2011-08-18 or greater. Using 2011-01-18 results in an Invalid XML Document error.Bisitun
Since it's not mentioned anywhere here, I just want to add that this fix flows through to the Azure CDN if you're using it.Nubilous
Can I make a request to the Rest API via postman? I am getting this error: >The MAC signature found in the HTTP request is not the same as any computed signature.Shirberg
D
5

For those who are struggling with the Azure Service API and the tricky Authorization, I recommend the this very simple C# snippet that does exactly the same in a very simpler way (at least for me).

        var credentials = new Microsoft.WindowsAzure.Storage.Auth.StorageCredentials("storagename", "storagekey");
        var account = new Microsoft.WindowsAzure.Storage.CloudStorageAccount(credentials, true);
        var client = account.CreateCloudBlobClient();
        var properties = client.GetServiceProperties();
        properties.DefaultServiceVersion = "2013-08-15";
        client.SetServiceProperties(properties);

You'll need to add a nuget package WindowsAzure.Storage v9.3.3 (obsolete, but still works)

Dexamethasone answered 20/12, 2016 at 21:59 Comment(2)
Any way to achieve this in php/Laravel ?Shirberg
You might need this: Protocol version support for .NET client library versions (REST API) - Azure Storage | Microsoft Learn.Gaziantep
P
3

I reached out to some members of the product team and was given the following...

The 200 vs 206 is due to the presents of the "-I" flag in the curl command. This results in a HEAD request instead of a GET which is essentially as "get blob properties" call instead of a "get blob" which will cause the range header to be ignored. Also be sure to specify the version headers as "x-ms-version:2011-08-18" or later since the "startByte-" range format was only supported on that version of later.

For more information on range headers, see: http://msdn.microsoft.com/en-us/library/windowsazure/ee691967.aspx

Pore answered 10/7, 2013 at 14:27 Comment(7)
Hi Brent, I did some testing tonight and modified my curl command to fetch the file and write the headers of the response to a separate file. Doing this I was able to confirm that when the starting and ending byte of the range is specified, a 206 response is returned, however when the ending byte is not specified (I.E., "-r 500-"), a 200 status is returned. According to this page: msdn.microsoft.com/en-us/library/windowsazure/ee691967.aspx the open-ended format is supported for range requests, so these requests should return a 206, correct?Cusco
did you remove the "-I" flag?Pore
Yes, here's an example: curl -i -o 1.mp3 "murfie.blob.core.windows.net/168464/…" -D 1mp3head.txt -r 500-Cusco
um, its still there, first parameterPore
That's lower-case "i", ("Include protocol headers in the output (H/F)") not upper-case "I" ("Show document info only")Cusco
kk. I'll check again and see what I get back. :)Pore
It's a little unfortunate that the 'get blob properties' call doesn't return the 'Accept-Ranges' header. Some systems expect the same set of headers for a HEAD request as a GET request, and use the HEAD request to determine if Range requests are even possible. With the current implementation, the system has to try real a range request, and then fallback to full download if it doesn't get a range.Desulphurize
F
2

Yes, it works. I've used SAS to stream video to mobile phones, which use Range headers.

Its easy to verify with a bit of code too.

Fendig answered 2/7, 2013 at 16:44 Comment(0)
G
2

We can also set the default version for Blob service by command az storage account blob-service-properties update --default-service-version with Azure-CLI.

$ account_name='foo'  # AZURE_STORAGE_ACCOUNT will do nothing

$ az storage account blob-service-properties show \
    --account-name "$account_name" | jq '.defaultServiceVersion'
null
> curl -I -XGET --range 500- "https://..."

HTTP/1.1 200 OK
x-ms-version: 2009-09-19

After setting the default version to "2011-08-18":

$ az storage account blob-service-properties update \
    --account-name "$account_name" \
    --default-service-version '2011-08-18' | jq '.defaultServiceVersion'
"2011-08-18"
> curl -I -XGET --range 500- "https://..."

HTTP/1.1 206 Partial Content
Content-Range: bytes 500-...
x-ms-version: 2011-08-18

I'm using az storage account blob-service-properties ... , while there is also an az storage blob service-properties command group:

$ az storage blob service-properties show \
    --account-name "$account_name" | jq '.target_version'
WARNING: 
...
"2011-08-18"

It appears that the former is newer. In "Release notes & updates – Azure CLI | Microsoft Learn":

December 17, 2019

2.0.78

Storage

  • Added new commands az storage account blob-service-properties show and az storage account blob-service-properties update --enable-change-feed to manage blob service properties for storage account.
Gaziantep answered 22/6, 2023 at 16:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.