RestSharp使用详解
看了张善友老师的几篇文章后决定认真学习一下Restfull风格的API开发和调用,于是先选用了RestSharp 作为客户端进行练习。调用的服务为阿里巴巴提供的开放存储服务。
阿里巴巴云存储服务提供了50G的免费空间以及每个月10G的流量,非常适合我们做点小应用。具体的API规则请查阅 OSS存储服务开发文档 。
1、推荐的使用方式
直接上代码啦~
public class AliyunApi
{
const string BaseUrl = " http://storage.aliyun测试数据 " ;
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 , 阿里云
作者: Leo_wl
出处: http://HdhCmsTestcnblogs测试数据/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息