zoukankan      html  css  js  c++  java
  • RestSharp使用详解

      看了张善友老师的几篇文章后决定认真学习一下Restfull风格的API开发和调用,于是先选用了RestSharp 作为客户端进行练习。调用的服务为阿里巴巴提供的开放存储服务。

    阿里巴巴云存储服务提供了50G的免费空间以及每个月10G的流量,非常适合我们做点小应用。具体的API规则请查阅OSS存储服务开发文档

    1、推荐的使用方式

    直接上代码啦~

    复制代码
        public class AliyunApi
        {
            const string BaseUrl = "http://storage.aliyun.com";
    
            readonly string _accountSid;
            readonly string _secretKey;
    
            public AliyunApi(string accountSid, string secretKey)
            {
                _accountSid = accountSid;
                _secretKey = secretKey;
            }
            //返回的XML或Josn对象直接反序列为实体对象
            public T Execute<T>(RestRequest request) where T : new()
            {
                var client = new RestClient();
                client.BaseUrl = BaseUrl;
                client.Authenticator = new AliyunAuthenticator(_accountSid, _secretKey);
    
                string date = DateTime.UtcNow.ToString("r");
                request.AddHeader(Constants.DATE, date);
                var response = client.Execute<T>(request);
                if ((int)response.StatusCode / 100 != 2)
                {
                    throw new OssException(response);
                }
                return response.Data;
            }
         //返回信息没有Body的对象
    public IRestResponse Execute(RestRequest request) { var client = new RestClient(); client.BaseUrl = BaseUrl; client.Authenticator = new AliyunAuthenticator(_accountSid, _secretKey); string date = DateTime.UtcNow.ToString("r"); request.AddHeader(Constants.DATE, date); var response = client.Execute(request); if ((int)response.StatusCode / 100 != 2) { throw new OssException(response); } return response; } //列出所有的Bucket public ListAllMyBucketsResult ListAllMyBuckets() { var request = new RestRequest(); request.Resource = "/"; request.Method = Method.GET; //request.AddParameter("CallSid", callSid, ParameterType.UrlSegment); return Execute<ListAllMyBucketsResult>(request); }      //创建一个Bucket
    public void PutBucket(string bucket, string per) { if (!Utils.ValidateBucketName(bucket)) { throw new ArgumentException("Unsupported bucket name:" + bucket); } var request = new RestRequest(); request.Resource = "/" + bucket + "/"; request.Method = Method.PUT; request.AddHeader(Constants.ACL, per); var response = Execute(request); } }
    复制代码

    上面定义了两个Execute方法,一个可以返回泛型结果T一个用于没有返回实体对象操作的。下面分别定义了ListAllMyBuckets来列出我所创建的所有Bucket,PutBucket用于创建一个新的Bucket。

    2、错误处理

    细心的朋友一定注意到了返回错误的处理方式:

                if ((int)response.StatusCode / 100 != 2)
                {
                    
    throw new OssException(response);
                }
    在RestSharp的HttpResponse 类型中定义了两个有关Http状态的字段分别为:

    1:System.Net.HttpStatusCode枚举类型的StatusCode

    2:RestSharp.ResponseStatus枚举类型的ResponseStatus

    除网络连接失败,DNS请求失败等原因ResponseStatus均为 Completed。

    HttpStatusCode才是用来描述web服务器发回来的状态,也就是我们常说的200、301、404、500等http头。

    System.Net.HttpStatusCode 在定义中关于200的一共有一下7种

            OK = 200,
            Created = 201,
            Accepted = 202,
            NonAuthoritativeInformation = 203,
            NoContent = 204,
            ResetContent = 205,
            PartialContent = 206,

    也就是说200以内的都是成功的请求,因此单纯判断(response.StatusCode==HttpStatusCode.OK),可能出现意外。

    3、自定义验证

    自定义验证相对简单了,根据OSS文档要求就可以了代码如下:

     public class AliyunAuthenticator : IAuthenticator
        {
            private const string DEFINE_PREFIX = "x-oss-";
            private const string ALGORITHM = "HmacSHA1";
    
            private readonly string accessKeyId;
            private readonly string secretAccessKey;
    
            public AliyunAuthenticator(string accessKeyId, string secretAccessKey)
            {
                this.secretAccessKey = secretAccessKey;
                this.accessKeyId = accessKeyId;
            }
            public void Authenticate(IRestClient client, IRestRequest request)
            {
                IEnumerable<Parameter> headers = request.Parameters.Where(m => m.Type == ParameterType.HttpHeader);
                IDictionary<string, string> dHeaders = new Dictionary<string, string>();
    
                foreach (Parameter p in headers)
                {
                    dHeaders.Add(p.Name, p.Value.ToString());
                }
    
    
                if (!string.IsNullOrEmpty(secretAccessKey) && !string.IsNullOrEmpty(accessKeyId))
                {
                    string resource = request.Resource;
                    if(request.Resource.IndexOf("client.BaseUrl")>0)
                        resource = request.Resource.Remove(0, client.BaseUrl.Length);
                    string authValue = "OSS "
                         + this.accessKeyId
                         + ":"
                         + GetAssign(secretAccessKey, request.Method.ToString(), dHeaders, resource);
    
                    request.AddHeader(Constants.AUTHORIZATION, authValue);
                }
                else if (!string.IsNullOrEmpty(accessKeyId))
                {
                    request.AddHeader(Constants.AUTHORIZATION, accessKeyId);
                }
            }
    
            private static string GetAssign(string secretAccessKey, string method,
                IDictionary<string, string> headers, string resource)
            {
                StringBuilder canonicalizedOssHeaders = new StringBuilder();
                StringBuilder stringToSign = new StringBuilder();
                byte[] byteHMAC = null;
                string contentMd5 = SafeGetElement(Constants.CONTENT_MD5, headers);
                string contentType = SafeGetElement(Constants.CONTENT_TYPE, headers);
                string date = SafeGetElement(Constants.DATE, headers);
                string canonicalizedResource = resource;
    
    
                SortedDictionary<string, string> tmpHeaders = formatHeader(headers);
                if (tmpHeaders.Count > 0)
                {
                    foreach (string key in tmpHeaders.Keys)
                    {
                        if (key.ToLower().StartsWith(DEFINE_PREFIX))
                        {
                            canonicalizedOssHeaders.Append(key).Append(":")
                                    .Append(tmpHeaders[key]).Append("\n");
                        }
                    }
                }
                stringToSign.Append(method).Append("\n").Append(contentMd5)
                        .Append("\n").Append(contentType).Append("\n").Append(date)
                        .Append("\n").Append(canonicalizedOssHeaders)
                        .Append(canonicalizedResource);
                try
                {
                    Encoding encoding = ASCIIEncoding.GetEncoding(Constants.CHARSET);
                    byte[] keyBytes = encoding.GetBytes(secretAccessKey);
                    KeyedHashAlgorithm hmac = KeyedHashAlgorithm.Create(ALGORITHM);
                    hmac.Key = keyBytes;
                    byteHMAC = hmac.ComputeHash(encoding.GetBytes(stringToSign.ToString()));
                }
                catch (Exception e)
                {
                }
                return Convert.ToBase64String(byteHMAC);
            }
    
            private static SortedDictionary<string, string> formatHeader(
            IDictionary<string, string> headers)
            {
                SortedDictionary<string, string> tmpHeaders = new SortedDictionary<string, string>();
    
                foreach (string key in headers.Keys)
                {
                    if (key.ToLower().StartsWith(DEFINE_PREFIX))
                    {
                        tmpHeaders[key.ToLower()] = headers[key];
                    }
                    else
                    {
                        tmpHeaders[key] = headers[key];
                    }
                }
                return tmpHeaders;
            }
    
            private static string SafeGetElement(string key, IDictionary<string, string> map)
            {
                if (map == null || !map.ContainsKey(key))
                {
                    return "";
                }
                return map[key];
            }
        }
    复制代码
        public class AliyunAuthenticator : IAuthenticator
        {
            private const string DEFINE_PREFIX = "x-oss-";
            private const string ALGORITHM = "HmacSHA1";
    
            private readonly string accessKeyId;
            private readonly string secretAccessKey;
    
            public AliyunAuthenticator(string accessKeyId, string secretAccessKey)
            {
                this.secretAccessKey = secretAccessKey;
                this.accessKeyId = accessKeyId;
            }
            public void Authenticate(IRestClient client, IRestRequest request)
            {
                IEnumerable<Parameter> headers = request.Parameters.Where(m => m.Type == ParameterType.HttpHeader);
                IDictionary<string, string> dHeaders = new Dictionary<string, string>();
    
                foreach (Parameter p in headers)
                {
                    dHeaders.Add(p.Name, p.Value.ToString());
                }
    
    
                if (!string.IsNullOrEmpty(secretAccessKey) && !string.IsNullOrEmpty(accessKeyId))
                {
                    string resource = request.Resource;
                    if(request.Resource.IndexOf("client.BaseUrl")>0)
                        resource = request.Resource.Remove(0, client.BaseUrl.Length);
                    string authValue = "OSS "
                         + this.accessKeyId
                         + ":"
                         + GetAssign(secretAccessKey, request.Method.ToString(), dHeaders, resource);
    
                    request.AddHeader(Constants.AUTHORIZATION, authValue);
                }
                else if (!string.IsNullOrEmpty(accessKeyId))
                {
                    request.AddHeader(Constants.AUTHORIZATION, accessKeyId);
                }
            }
    
            private static string GetAssign(string secretAccessKey, string method,
                IDictionary<string, string> headers, string resource)
            {
                StringBuilder canonicalizedOssHeaders = new StringBuilder();
                StringBuilder stringToSign = new StringBuilder();
                byte[] byteHMAC = null;
                string contentMd5 = SafeGetElement(Constants.CONTENT_MD5, headers);
                string contentType = SafeGetElement(Constants.CONTENT_TYPE, headers);
                string date = SafeGetElement(Constants.DATE, headers);
                string canonicalizedResource = resource;
    
    
                SortedDictionary<string, string> tmpHeaders = formatHeader(headers);
                if (tmpHeaders.Count > 0)
                {
                    foreach (string key in tmpHeaders.Keys)
                    {
                        if (key.ToLower().StartsWith(DEFINE_PREFIX))
                        {
                            canonicalizedOssHeaders.Append(key).Append(":")
                                    .Append(tmpHeaders[key]).Append("\n");
                        }
                    }
                }
                stringToSign.Append(method).Append("\n").Append(contentMd5)
                        .Append("\n").Append(contentType).Append("\n").Append(date)
                        .Append("\n").Append(canonicalizedOssHeaders)
                        .Append(canonicalizedResource);
                try
                {
                    Encoding encoding = ASCIIEncoding.GetEncoding(Constants.CHARSET);
                    byte[] keyBytes = encoding.GetBytes(secretAccessKey);
                    KeyedHashAlgorithm hmac = KeyedHashAlgorithm.Create(ALGORITHM);
                    hmac.Key = keyBytes;
                    byteHMAC = hmac.ComputeHash(encoding.GetBytes(stringToSign.ToString()));
                }
                catch (Exception e)
                {
                }
                return Convert.ToBase64String(byteHMAC);
            }
    
            private static SortedDictionary<string, string> formatHeader(
            IDictionary<string, string> headers)
            {
                SortedDictionary<string, string> tmpHeaders = new SortedDictionary<string, string>();
    
                foreach (string key in headers.Keys)
                {
                    if (key.ToLower().StartsWith(DEFINE_PREFIX))
                    {
                        tmpHeaders[key.ToLower()] = headers[key];
                    }
                    else
                    {
                        tmpHeaders[key] = headers[key];
                    }
                }
                return tmpHeaders;
            }
    
            private static string SafeGetElement(string key, IDictionary<string, string> map)
            {
                if (map == null || !map.ContainsKey(key))
                {
                    return "";
                }
                return map[key];
            }
        }
    复制代码

    上面只是把基本的结构分析了一下,看似简单,在应用过程中,遇到了很多麻烦。下一篇在分析使用过程中遇到的具体问题了,欢迎拍砖。

     
     
    标签: Restfull阿里云
  • 相关阅读:
    Superset 制作图表
    superset 安装配置
    python 虚拟环境 pyenv
    pymysql 单独获取表的栏位名称
    pymysql 返回数据为字典形式(key:value--列:值)
    Oracle/MySQL decimal/int/number 转字符串
    netstat 问题处理
    MySQL 中Index Condition Pushdown (ICP 索引条件下推)和Multi-Range Read(MRR 索引多范围查找)查询优化
    MySQL执行计划extra中的using index 和 using where using index 的区别
    ref与out
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2511159.html
Copyright © 2011-2022 走看看