locked
AddRange on GET BLOB does not work in Devfabric RRS feed

  • Question

  • Hi,

    I need to progressively download a video from Azure blob. I am not using StorageClient.dll and implenting the REST based calls. I am testing this on dev fabric. If I download the complete video in one shot, it works.

    However, if I use AddRange and specify a byte range, I get a 403 Forbidden Access exception. I have tried using Addrange on Httprequest as well as using the "x-ms-range" header in the REST API but I receive the same error.

    Should "x-ms-range" be also added to canonicalized headers? Please share your thoughts.

    -regards,

    Gaurav

    Tuesday, December 27, 2011 10:38 AM

Answers

  • Hi Gaurav,

    One thing I noticed is that you have not added "x-ms-range" header in "canonicalizedHeaders". Please take a look at http://msdn.microsoft.com/en-us/library/dd179428.aspx section titled "Constructing the Canonicalized Headers String" and it mentions that you would need to include all the headers which starts with x-ms- for constructing "canonicalizedHeaders" string.

    Based on that, your canonicalizedHeaders should be:

    String canonicalizedHeaders = String.Format("x-ms-date:{0}\nx-ms-range:{1}\nx-ms-version:{2}", date, "bytes=0-10000", msVersion);

    Hope this helps.

    Thanks

    Gaurav

    Tuesday, December 27, 2011 12:52 PM

All replies

  • Can you share your code for creating authorization header? Most likely you're getting this error because of improper authorization header.You would need to pass the range there as well (http://msdn.microsoft.com/en-us/library/dd179428.aspx).

    Hope this helps.

    Thanks

    Gaurav Mantri

    Cerebrata Software

    http://www.cerebrata.com

     

     

    Tuesday, December 27, 2011 11:30 AM
  • Hi Gaurav,

    I tried the way you have suggested but still getting the same execption. Yes, in the stack trace I can see that it is because the authorization header is malformed.

    This is the code block I am using:

      func1()
             {  
                string requestMethod = "GET";
                String urlPath = String.Format("{0}/{1}", containerName, blobName);

                //Development storage
               String urlPathResource = "devstoreaccount1" + "/" + urlPath;
               
                String msVersion = "2009-09-19";
                String date = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);
                String canonicalizedHeaders = String.Format("x-ms-date:{0}\nx-ms-version:{1}", date, msVersion);

                String canonicalizedResource = String.Format("/{0}/{1}", "devstoreaccount1", urlPathResource);
                String stringToSign = String.Format("{0}\n\n\n\n\n\n\n\n\n\n\n{3}\n{1}\n{2}", requestMethod, canonicalizedHeaders,   canonicalizedResource, "bytes=0-10000");

                String authorizationHeader = CreateAuthorizationHeader(stringToSign);

                Uri uri = new Uri(@"http://127.0.0.1:10000/devstoreaccount1/" + urlPath);
                request = (HttpWebRequest)WebRequest.Create(uri);
                request.Method = requestMethod;
                request.Headers.Add("x-ms-date", date);
                request.Headers.Add("x-ms-version", msVersion);
                request.Headers.Add("Authorization", authorizationHeader);
                request.Headers.Add("Accept-Charset", "UTF-8");
                request.Accept = "application/atom+xml,application/xml";
                request.Headers.Add("x-ms-range", "bytes=0-10000");

           reponse = (

    HttpWebResponse)this.request.GetResponse();

           Stream

    responseStream = reponse.GetResponseStream();

     


              }

         private String CreateAuthorizationHeader(String canonicalizedString)
                {
                 String signature = string.Empty;
                    using (HMACSHA256 hmacSha256 = new HMACSHA256(Convert.FromBase64String              (@"Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==")))
                {
                    Byte[] dataToHmac = System.Text.Encoding.UTF8.GetBytes(canonicalizedString);
                    signature = Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac));
                }
                 String authorizationHeader = String.Format(CultureInfo.InvariantCulture, "{0} {1}:{2}", "SharedKey", "devstoreaccount1", signature);
                 return authorizationHeader;
                }       

     Please suggest if you see anything wrong here.

    -regards,

    Gaurav

    Tuesday, December 27, 2011 12:39 PM
  • Hi Gaurav,

    One thing I noticed is that you have not added "x-ms-range" header in "canonicalizedHeaders". Please take a look at http://msdn.microsoft.com/en-us/library/dd179428.aspx section titled "Constructing the Canonicalized Headers String" and it mentions that you would need to include all the headers which starts with x-ms- for constructing "canonicalizedHeaders" string.

    Based on that, your canonicalizedHeaders should be:

    String canonicalizedHeaders = String.Format("x-ms-date:{0}\nx-ms-range:{1}\nx-ms-version:{2}", date, "bytes=0-10000", msVersion);

    Hope this helps.

    Thanks

    Gaurav

    Tuesday, December 27, 2011 12:52 PM
  • Thanks Gaurav. What you suggested is right and worked. In addition, I had to get rid of below lines of code.

    request.Headers.Add("Accept-Charset", "UTF-8");

    request.Accept = "application/atom+xml,application/xml";

     

    -regards,

    Gaurav

    Friday, December 30, 2011 5:23 AM