0
votes

I have an issue with azure storage blob is not returning 206 Partial content for video files.

Problem: videos are fully downloaded(20-40s for 300mb videos) and the seek bar is not working. I am using Laravel and this problem occurs only when I try to retrieve the .mp4 files from Azure Blob Storage. It was working fine when I was storing the media files on the public disk.

A microsoft employee states that changing the x-ms-version to 2011-01-18 or later will fix my issue. LINK to the discussion:

Microsoft have a post related to setting the blob servic properties: HERE

Note their sample for achieving that: https://docs.microsoft.com/en-us/rest/api/storageservices/set-blob-service-properties#sample-request-and-response

I am trying to send the request via Postman like this:

PUT https://{account-name}.blob.core.windows.net/?restype=service&comp=properties

Included Headers and Response in Postman: enter image description here

I searched for the error and found this question on SO: The MAC signature found in the HTTP request '...' is not the same as any computed signature

It has an accepted answer but I don't seem to get it. Is there something wrong with my Request/ Authorization header? Or I need to take a different approach?

Thanks in advance!

My code in LARAVEL:

 $date = gmdate('D, d M Y H:i:s \G\M\T');
    $account_name = "xyz";
    $containername = "media";
    $account_key = "access_key";

    $canonicalizedHeaders  = "x-ms-date:$date\nx-ms-version:2017-11-09";
    $canonicalizedResource = "/$account_name/$containername\ncomp:list\nrestype:container";

    $arraysign = array();
    $arraysign[] = 'GET';                     /*HTTP Verb*/
    $arraysign[] = '';                        /*Content-Encoding*/
    $arraysign[] = '';                        /*Content-Language*/
    $arraysign[] = '';                        /*Content-Length (include value when zero)*/
    $arraysign[] = '';                        /*Content-MD5*/
    $arraysign[] = '';                        /*Content-Type*/
    $arraysign[] = '';                        /*Date*/
    $arraysign[] = '';                        /*If-Modified-Since */
    $arraysign[] = '';                        /*If-Match*/
    $arraysign[] = '';                        /*If-None-Match*/
    $arraysign[] = '';                        /*If-Unmodified-Since*/
    $arraysign[] = '';                        /*Range*/
    $arraysign[] = $canonicalizedHeaders;     /*CanonicalizedHeaders*/
    $arraysign[] = $canonicalizedResource;    /*CanonicalizedResource*/

    $stringtosign = implode("\n", $arraysign);

    $signature = 'SharedKey' . ' ' . $account_name . ':' . base64_encode(hash_hmac('sha256', $stringtosign, base64_decode($account_key), true));

    $endpoint = 'https://' . $account_name . '.blob.core.windows.net';
    $url = $endpoint . '/' . $containername . '?restype=container';

    $headers = [
        "x-ms-date:{$date}",
        'x-ms-version:2017-11-09',
        'Accept:application/json;odata=nometadata',
        "Authorization:{$signature}"
    ];

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $response  = curl_exec($ch);
    echo curl_error($ch);
    curl_close($ch);
    echo '<pre>';
    print_r($response);
2
Did you put the storage key as the shared key in the request header?1_1
Hi @BowmanZhu , I am using the access key from the portal. I am not sure if the access key is equivalent to 'storage' key? Also, is there a way to achieve this in postman?brpetrov
REST API should not use this. The value after 'SharedKey:' is sign from headers and storage key(This can only generate from code,). You can’t get this value just by using postman, you need to use code generation, and then paste it after the'SharedKey'.1_1
Generation is very troublesome, and every REST API is different, I can help you find related things (if you need it). :)1_1
That would be pretty helpful. Do I need the key and connection string from Access Keys in azure portlal?brpetrov

2 Answers

0
votes

I can reproduce your error when using Shared key(This problem comes from you give the storage account key instead of the key after signed by HMAC.):

enter image description here

But if I use AD bearer token, then it will be no problem:

enter image description here

Python code to get the bearer token:

import requests
from azure.identity import ClientSecretCredential 

client_id = 'xxx'
tenant_id = 'xxx'
client_secret = 'xxx'

credential = ClientSecretCredential(tenant_id=tenant_id, client_id=client_id, client_secret=client_secret)
accesstoken = str(credential.get_token('https://yourstoragename.blob.core.windows.net/.default'))[19:1282]
print(str(credential.get_token('https://yourstoragename.blob.core.windows.net/.default')))
0
votes

I suggest you should use SAS token instead of shared key for authentication. SAS token is easy to generate and manage.

Here are the steps to set blob service properties by using SAS token:

1.Nav to azure portal -> your storage account -> Settings -> Shared access signature: select the proper options as per your need -> Then click "Generate SAS and connection string" button -> at last, after the SAS token is generated, copy and save it in some editors like .txt file. The screenshot like below:

enter image description here

2.Build the url with SAS token. For example, the request url is https://xx.blob.core.windows.net/?restype=service&comp=properties, then put the SAS token at the end of the request url. Note: you should remove the first "?" from the SAS token, and put a "&" at the beginning of SAS token.

If the SAS token is ?sv=2020-02-10&ss=b&srt=sco&sp=rwdlacx&se=2021-02-25T10:44:44Z&st=2021-02-25T02:44:44Z&spr=https&sig=xx

Then the request url with SAS token should look like below:

https://xx.blob.core.windows.net/?restype=service&comp=properties&sv=2020-02-10&ss=b&srt=sco&sp=rwdlacx&se=2021-02-25T10:44:44Z&st=2021-02-25T02:44:44Z&spr=https&sig=xxx

3.In postman, use the request url with SAS token as request url, and in the Headers tab, just fill in the 2 headers x-ms-date and x-ms-version. Since we use SAS token, then no need to use Authorization header. Here is the screenshot:

enter image description here

4.In the Body tab, write the proper request body as per the Request Body doc. Since I'm using x-ms-version == 2020-04-08, I follow this section "For version 2019-12-12 or later, the format of the request body is as follows:" in the doc. The screenshot as below(I just modify the soft-delete property, and its retention period):

enter image description here

5.After run the test, In postman, I can see the response code is 202. And in azure portal, the soft-delete property is turned on, and the retention period is also set correctly:

enter image description here