技术开发 频道

Windows Azure入门:REST API的用法

  【IT168-微软云计算博客征文活动专稿】本文将会介绍如何使用REST API来直接访问Storage Service。

  在前三篇教学中,我们已经学习了使用Windows Azure SDK所提供的StorageClient来使用Blob Storage, Queue Storage以及Table Storage的基本方法。我们在前几篇教学中也提及最终StorageClient也是通过发送REST请求来与服务器端通信的。在这篇教学中,我们会以Blob Storage为例,说明如何使用RESTAPI直接与服务器进行通信。需要说明的是,这篇教学中使用的是C#语言。但是由于RESTAPI实际上是通过HTTP发送的HTTP消息,使用其他语言的工程师同样可以参考代码逻辑了解如何构造HTTP消息以便在其他编程语言中使用。

  步骤一:准备工作

  在本教学中我们将使用List Blobs API:

  该API的作用是返回给定的Container中的Blob信息。为了测试我们的代码我们首先需要有一个已经创建的Container并且向其中添加至少一个Blob。由于如何添加Container和Blob的方法我们已经在Windows Azure入门教学系列 (四):使用Blob Storage中提过,在此不赘述。读者可以按照Windows Azure入门教学系列 (四):使用Blob Storage中的代码创建名为helloworldcontainer的Container和名为myfile的Blob。(只需注释掉删除Blob的代码并运行程序即可)

  步骤二:创建解决方案和项目

  由于我们要在本地模拟环境下测试Table Storage,首先,请确保Development Storage的管理器程序已经启动。我们可以找到管理器的进程手动启动或者让Visual Studio帮助我们启动他。

  右击工具栏中Development Fabric的图标,选择”Show Development Storage UI”。弹出如下图所示的窗口:

使用REST API访问Storage Service

  我们要关注的是Service management中Blob所在的一行。要确保Status为Running。

  确认完毕后启动Visual Studio,并且新建一个Console项目。

  步骤三:添加程序集引用

  在Console项目中添加对System.Web程序集的引用。该程序集安装在GAC中。在.NET标签下能够找到该程序集。我们将使用该程序集来发送HTTP请求和接受HTTP消息。

  步骤四:添加代码

  首先在项目中的Program.cs中引用命名空间:

using System.IO;

  
using System.Collections.Specialized;

  
using System.Collections;

  
using System.Web;

 

    然后在Program.cs中添加如下代码:

class Program

    {

        internal
class CanonicalizedString

        {

            
private StringBuilder canonicalizedString = new StringBuilder();



            internal CanonicalizedString(
string initialElement)

            {

                this.canonicalizedString.Append(initialElement);

            }



            internal void AppendCanonicalizedElement(
string element)

            {

                this.canonicalizedString.Append(
"\n");

                this.canonicalizedString.Append(element);

            }

            internal
string Value

            {

                
get

                {

                    
return this.canonicalizedString.ToString();

                }

            }

        }

        
const string bloburi = @"http://127.0.0.1:10000/devstoreaccount1";

        
const string accountname = "devstoreaccount1";

        
const string key = "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==";

        
const string method = "GET";

        
static void Main(string[] args)

        {

            
string AccountName = accountname;

            
string AccountSharedKey = key;

            
string Address = bloburi;

            
string container = "helloworldcontainer";  

            
// 创建请求字符串

            
string QueryString = "?restype=container&comp=list";

            Uri requesturi
= new Uri(Address + "/" + container + QueryString);

            
string MessageSignature = "";

            
// 创建HttpWebRequest类

            HttpWebRequest Request
= (HttpWebRequest)HttpWebRequest.Create(requesturi.AbsoluteUri);

            Request.Method
= method;

            Request.ContentLength
= 0;

            Request.Headers.Add(
"x-ms-date", DateTime.UtcNow.ToString("R"));

            Request.Headers.Add(
"x-ms-version", "2009-09-19");

            
// 开始创建签名

            MessageSignature
+= "GET\n"; //Verb

            MessageSignature
+= "\n"; // Content-Encoding

            MessageSignature
+= "\n"; // Content-Language

            MessageSignature
+= "\n"; // Content-Length

            MessageSignature
+= "\n"; // Content-MD5

            MessageSignature
+= "\n"; // Content-Type

            MessageSignature
+= "\n"; // Date

            MessageSignature
+= "\n"; // If-Modified-Since

            MessageSignature
+= "\n"; // If-Match

            MessageSignature
+= "\n"; // If-None-Match

            MessageSignature
+= "\n"; // If-Unmodified-Since

            MessageSignature
+= "\n"; // Range

            
// CanonicalizedHeaders

            ArrayList list
= new ArrayList();

            foreach (
string str in Request.Headers.Keys)

            {

                
if (str.ToLowerInvariant().StartsWith("x-ms-", StringComparison.Ordinal))

                {

                    list.Add(
str.ToLowerInvariant());

                }

            }

            list.Sort();

            foreach (
string str2 in list)

            {

                StringBuilder builder
= new StringBuilder(str2);

                
string str3 = ":";

                foreach (
string str4 in GetHeaderValues(Request.Headers, str2))

                {

                    
string str5 = str4.Replace("\r\n", string.Empty);

                    builder.Append(str3);

                    builder.Append(str5);

                    str3
= ",";

                }

                MessageSignature
+=builder.ToString()+"\n";

            }

            MessageSignature
+= GetCanonicalizedResourceVersion2(requesturi, AccountName);

            
// 用HMAC-SHA256对签名编码

            
byte[] SignatureBytes = System.Text.Encoding.UTF8.GetBytes(MessageSignature);

            System.Security.Cryptography.HMACSHA256 SHA256
= new System.Security.Cryptography.HMACSHA256(Convert.FromBase64String(AccountSharedKey));

            
// 创建Authorization HTTP消息头的值

            
String AuthorizationHeader = "SharedKey " + AccountName + ":" + Convert.ToBase64String(SHA256.ComputeHash(SignatureBytes));

            
// 把编码后的签名加入到Authorization HTTP消息头中

            Request.Headers.Add(
"Authorization", AuthorizationHeader);

            
// 获取返回消息

            
using (HttpWebResponse response = (HttpWebResponse)Request.GetResponse())

            {

                
if (response.StatusCode == HttpStatusCode.OK)

                {

                    
// 服务器返回成功消息

                    
using (Stream stream = response.GetResponseStream())

                    {

                        
using (StreamReader sr = new StreamReader(stream))

                        {



                            var s
= sr.ReadToEnd();

                            
// 输出返回消息

                            Console.WriteLine(s);

                        }

                      

                    }

                }

                
else

                {

                    
// 这里可以抛出异常信息

                }

            }

            Console.ReadLine();



        }

        
static  ArrayList GetHeaderValues(NameValueCollection headers, string headerName)

        {

            ArrayList list
= new ArrayList();

            
string[] values = headers.GetValues(headerName);

            
if (values != null)

            {

                foreach (
string str in values)

                {

                    list.Add(
str.TrimStart(new char[0]));

                }

            }

            
return list;

        }

        
static string GetCanonicalizedResourceVersion2(Uri address, string accountName)

        {

            StringBuilder builder
= new StringBuilder("/");

            builder.Append(accountName);

            builder.Append(address.AbsolutePath);

            CanonicalizedString
str = new CanonicalizedString(builder.ToString());

            NameValueCollection values
= HttpUtility.ParseQueryString(address.Query);

            NameValueCollection values2
= new NameValueCollection();

            foreach (
string str2 in values.Keys)

            {

                ArrayList list
= new ArrayList(values.GetValues(str2));

                list.Sort();

                StringBuilder builder2
= new StringBuilder();

                foreach (
object obj2 in list)

                {

                    
if (builder2.Length > 0)

                    {

                        builder2.Append(
",");

                    }

                    builder2.Append(obj2.ToString());

                }

                values2.Add((str2
== null) ? str2 : str2.ToLowerInvariant(), builder2.ToString());

            }

            ArrayList list2
= new ArrayList(values2.AllKeys);

            list2.Sort();

            foreach (
string str3 in list2)

            {

                StringBuilder builder3
= new StringBuilder(string.Empty);

                builder3.Append(str3);

                builder3.Append(
":");

                builder3.Append(values2[str3]);

                
str.AppendCanonicalizedElement(builder3.ToString());

            }

            
return str.Value;

        }



    }

  步骤五:观察并分析代码

  我们首先观察下面三行代码:

const string bloburi = @"http://127.0.0.1:10000/devstoreaccount1";

  
const string accountname = "devstoreaccount1";

  
const string key = "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==";

  这三行代码定义了Blob Storage服务端口,我们使用的账户名和密码。由于使用的是本地模拟的Storage,所以必须使用固定的端口地址,用户名以及密码。

  在代码中,我们使用HttpWebRequest 构造并发送HTTP请求。

  在规定中说明了如果该container没有被设置为允许匿名访问,那么必须由于账户拥有者调用该API才能返回结果。要这样做必须添加Authorization HTTP消息头。我们必须严格按照下面一篇文档规定的格式来生成该HTTP消息头:

  步骤六:运行程序

使用REST API访问Storage Service

  如果一切正常,你将会看到Console程序输出如下信息,内容为名为helloworld的Container中所有Blob的信息:

0
相关文章