root / trunk / Pithos.Network / CloudFilesClient.cs @ 3c43ec9b
History | View | Annotate | Download (26.5 kB)
1 | d78cbf09 | Panagiotis Kanavos | using System; |
---|---|---|---|
2 | d78cbf09 | Panagiotis Kanavos | using System.Collections.Generic; |
3 | d78cbf09 | Panagiotis Kanavos | using System.ComponentModel.Composition; |
4 | 5bcf6d70 | Panagiotis Kanavos | using System.Diagnostics; |
5 | d78cbf09 | Panagiotis Kanavos | using System.Diagnostics.Contracts; |
6 | d78cbf09 | Panagiotis Kanavos | using System.IO; |
7 | d78cbf09 | Panagiotis Kanavos | using System.Linq; |
8 | d78cbf09 | Panagiotis Kanavos | using System.Net; |
9 | d78cbf09 | Panagiotis Kanavos | using System.Security.Cryptography; |
10 | d78cbf09 | Panagiotis Kanavos | using System.Text; |
11 | b5061ac8 | Panagiotis Kanavos | using System.Threading.Tasks; |
12 | d78cbf09 | Panagiotis Kanavos | using Hammock; |
13 | d78cbf09 | Panagiotis Kanavos | using Hammock.Caching; |
14 | d78cbf09 | Panagiotis Kanavos | using Hammock.Retries; |
15 | d78cbf09 | Panagiotis Kanavos | using Hammock.Serialization; |
16 | 5bcf6d70 | Panagiotis Kanavos | using Hammock.Tasks; |
17 | d78cbf09 | Panagiotis Kanavos | using Hammock.Web; |
18 | d78cbf09 | Panagiotis Kanavos | using Newtonsoft.Json; |
19 | d78cbf09 | Panagiotis Kanavos | using Pithos.Interfaces; |
20 | d78cbf09 | Panagiotis Kanavos | |
21 | d78cbf09 | Panagiotis Kanavos | namespace Pithos.Network |
22 | d78cbf09 | Panagiotis Kanavos | { |
23 | d78cbf09 | Panagiotis Kanavos | [Export(typeof(ICloudClient))] |
24 | d78cbf09 | Panagiotis Kanavos | public class CloudFilesClient:ICloudClient |
25 | d78cbf09 | Panagiotis Kanavos | { |
26 | 1482f9ad | Panagiotis Kanavos | string _rackSpaceAuthUrl = "https://auth.api.rackspacecloud.com"; |
27 | 3c43ec9b | Panagiotis Kanavos | private string _pithosAuthUrl = "https://pithos.dev.grnet.gr"; |
28 | 2c053915 | Panagiotis Kanavos | |
29 | d78cbf09 | Panagiotis Kanavos | private RestClient _client; |
30 | 5bcf6d70 | Panagiotis Kanavos | private readonly TimeSpan _shortTimeout = TimeSpan.FromSeconds(10); |
31 | d78cbf09 | Panagiotis Kanavos | private readonly int _retries = 5; |
32 | b5061ac8 | Panagiotis Kanavos | private RetryPolicy _retryPolicy; |
33 | d78cbf09 | Panagiotis Kanavos | public string ApiKey { get; set; } |
34 | d78cbf09 | Panagiotis Kanavos | public string UserName { get; set; } |
35 | b6c72f62 | Panagiotis Kanavos | public Uri StorageUrl { get; set; } |
36 | d78cbf09 | Panagiotis Kanavos | public string Token { get; set; } |
37 | 5bcf6d70 | Panagiotis Kanavos | public Uri Proxy { get; set; } |
38 | b5061ac8 | Panagiotis Kanavos | |
39 | b5061ac8 | Panagiotis Kanavos | public double DownloadPercentLimit { get; set; } |
40 | b5061ac8 | Panagiotis Kanavos | public double UploadPercentLimit { get; set; } |
41 | 2c053915 | Panagiotis Kanavos | |
42 | 2c053915 | Panagiotis Kanavos | public string AuthUrl |
43 | 2c053915 | Panagiotis Kanavos | { |
44 | 2c053915 | Panagiotis Kanavos | get { return UsePithos ? _pithosAuthUrl : _rackSpaceAuthUrl; } |
45 | 2c053915 | Panagiotis Kanavos | } |
46 | 1482f9ad | Panagiotis Kanavos | |
47 | 1482f9ad | Panagiotis Kanavos | public string VersionPath |
48 | 1482f9ad | Panagiotis Kanavos | { |
49 | 1482f9ad | Panagiotis Kanavos | get { return UsePithos ? "v1" : "v1.0"; } |
50 | 1482f9ad | Panagiotis Kanavos | } |
51 | 2c053915 | Panagiotis Kanavos | |
52 | 2c053915 | Panagiotis Kanavos | public bool UsePithos { get; set; } |
53 | d78cbf09 | Panagiotis Kanavos | |
54 | 3c43ec9b | Panagiotis Kanavos | private bool _authenticated = false; |
55 | 3c43ec9b | Panagiotis Kanavos | |
56 | d78cbf09 | Panagiotis Kanavos | public void Authenticate(string userName,string apiKey) |
57 | d78cbf09 | Panagiotis Kanavos | { |
58 | 0eea575a | Panagiotis Kanavos | Trace.TraceInformation("[AUTHENTICATE] Start for {0}", userName); |
59 | d78cbf09 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(userName)) |
60 | 0eea575a | Panagiotis Kanavos | throw new ArgumentNullException("userName", "The userName property can't be empty"); |
61 | d78cbf09 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(apiKey)) |
62 | d78cbf09 | Panagiotis Kanavos | throw new ArgumentNullException("apiKey", "The apiKey property can't be empty"); |
63 | d78cbf09 | Panagiotis Kanavos | |
64 | 3c43ec9b | Panagiotis Kanavos | if (_authenticated) |
65 | 3c43ec9b | Panagiotis Kanavos | return; |
66 | 3c43ec9b | Panagiotis Kanavos | |
67 | d78cbf09 | Panagiotis Kanavos | UserName = userName; |
68 | d78cbf09 | Panagiotis Kanavos | ApiKey = apiKey; |
69 | d78cbf09 | Panagiotis Kanavos | |
70 | 0eea575a | Panagiotis Kanavos | var proxy = Proxy != null ? Proxy.ToString() : null; |
71 | 0eea575a | Panagiotis Kanavos | if (UsePithos) |
72 | 0eea575a | Panagiotis Kanavos | { |
73 | 3c43ec9b | Panagiotis Kanavos | Token = ApiKey; |
74 | 0eea575a | Panagiotis Kanavos | string storageUrl = String.Format("{0}/{1}/{2}", AuthUrl, VersionPath, UserName); |
75 | 0eea575a | Panagiotis Kanavos | StorageUrl = new Uri(storageUrl); |
76 | 0eea575a | Panagiotis Kanavos | } |
77 | 0eea575a | Panagiotis Kanavos | else |
78 | 0eea575a | Panagiotis Kanavos | { |
79 | d78cbf09 | Panagiotis Kanavos | |
80 | 0eea575a | Panagiotis Kanavos | string authUrl = String.Format("{0}/{1}", AuthUrl, VersionPath); |
81 | 0eea575a | Panagiotis Kanavos | var authClient = new RestClient {Path = authUrl, Proxy = proxy}; |
82 | d78cbf09 | Panagiotis Kanavos | |
83 | 0eea575a | Panagiotis Kanavos | authClient.AddHeader("X-Auth-User", UserName); |
84 | 0eea575a | Panagiotis Kanavos | authClient.AddHeader("X-Auth-Key", ApiKey); |
85 | 0eea575a | Panagiotis Kanavos | |
86 | 0eea575a | Panagiotis Kanavos | var response = authClient.Request(); |
87 | 0eea575a | Panagiotis Kanavos | |
88 | 0eea575a | Panagiotis Kanavos | ThrowIfNotStatusOK(response, "Authentication failed"); |
89 | 0eea575a | Panagiotis Kanavos | |
90 | 0eea575a | Panagiotis Kanavos | var keys = response.Headers.AllKeys.AsQueryable(); |
91 | 0eea575a | Panagiotis Kanavos | |
92 | 0eea575a | Panagiotis Kanavos | string storageUrl = GetHeaderValue("X-Storage-Url", response, keys); |
93 | 0eea575a | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(storageUrl)) |
94 | 0eea575a | Panagiotis Kanavos | throw new InvalidOperationException("Failed to obtain storage url"); |
95 | 0eea575a | Panagiotis Kanavos | StorageUrl = new Uri(storageUrl); |
96 | d78cbf09 | Panagiotis Kanavos | |
97 | b6c72f62 | Panagiotis Kanavos | var token = GetHeaderValue("X-Auth-Token", response, keys); |
98 | b6c72f62 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(token)) |
99 | b6c72f62 | Panagiotis Kanavos | throw new InvalidOperationException("Failed to obtain token url"); |
100 | b6c72f62 | Panagiotis Kanavos | Token = token; |
101 | b6c72f62 | Panagiotis Kanavos | } |
102 | d78cbf09 | Panagiotis Kanavos | |
103 | b5061ac8 | Panagiotis Kanavos | _retryPolicy = new RetryPolicy { RetryCount = _retries }; |
104 | b5061ac8 | Panagiotis Kanavos | _retryPolicy.RetryConditions.Add(new TimeoutRetryCondition()); |
105 | 1482f9ad | Panagiotis Kanavos | |
106 | b5061ac8 | Panagiotis Kanavos | _client = new RestClient { Authority = StorageUrl.AbsoluteUri, Path = UserName, Proxy = proxy }; |
107 | b5061ac8 | Panagiotis Kanavos | _client.FileProgress += OnFileProgress; |
108 | 1482f9ad | Panagiotis Kanavos | |
109 | d78cbf09 | Panagiotis Kanavos | _client.AddHeader("X-Auth-Token", Token); |
110 | 0eea575a | Panagiotis Kanavos | /*if (UsePithos) |
111 | 2c053915 | Panagiotis Kanavos | { |
112 | 2c053915 | Panagiotis Kanavos | _client.AddHeader("X-Auth-User", UserName); |
113 | 1482f9ad | Panagiotis Kanavos | _client.AddHeader("X-Auth-Key",ApiKey); |
114 | 0eea575a | Panagiotis Kanavos | }*/ |
115 | 2c053915 | Panagiotis Kanavos | |
116 | b5061ac8 | Panagiotis Kanavos | Trace.TraceInformation("[AUTHENTICATE] End for {0}", userName); |
117 | b5061ac8 | Panagiotis Kanavos | } |
118 | d78cbf09 | Panagiotis Kanavos | |
119 | b5061ac8 | Panagiotis Kanavos | private void OnFileProgress(object sender, FileProgressEventArgs e) |
120 | b5061ac8 | Panagiotis Kanavos | { |
121 | b5061ac8 | Panagiotis Kanavos | Trace.TraceInformation("[PROGRESS] {0} {1:p} {2} of {3}",e.FileName,(double)e.BytesWritten/e.TotalBytes, e.BytesWritten,e.TotalBytes); |
122 | d78cbf09 | Panagiotis Kanavos | } |
123 | d78cbf09 | Panagiotis Kanavos | |
124 | d78cbf09 | Panagiotis Kanavos | public IList<ContainerInfo> ListContainers() |
125 | d78cbf09 | Panagiotis Kanavos | { |
126 | 1482f9ad | Panagiotis Kanavos | //Workaround for Hammock quirk: Hammock always |
127 | 1482f9ad | Panagiotis Kanavos | //appends a / unless a Path is specified. |
128 | 1482f9ad | Panagiotis Kanavos | |
129 | 1482f9ad | Panagiotis Kanavos | //Create a request with a complete path |
130 | b5061ac8 | Panagiotis Kanavos | var request = new RestRequest { Path = StorageUrl.ToString(), RetryPolicy = _retryPolicy,Timeout = _shortTimeout }; |
131 | d78cbf09 | Panagiotis Kanavos | request.AddParameter("format","json"); |
132 | 1482f9ad | Panagiotis Kanavos | //Create a client clone |
133 | 5bcf6d70 | Panagiotis Kanavos | var client = new RestClient{Proxy=Proxy.ToString()}; |
134 | 1482f9ad | Panagiotis Kanavos | foreach (var header in _client.GetAllHeaders()) |
135 | 1482f9ad | Panagiotis Kanavos | { |
136 | 1482f9ad | Panagiotis Kanavos | client.AddHeader(header.Name,header.Value); |
137 | 1482f9ad | Panagiotis Kanavos | } |
138 | 1482f9ad | Panagiotis Kanavos | |
139 | 1482f9ad | Panagiotis Kanavos | var response = client.Request(request); |
140 | d78cbf09 | Panagiotis Kanavos | |
141 | d78cbf09 | Panagiotis Kanavos | if (response.StatusCode == HttpStatusCode.NoContent) |
142 | d78cbf09 | Panagiotis Kanavos | return new List<ContainerInfo>(); |
143 | d78cbf09 | Panagiotis Kanavos | |
144 | 5bcf6d70 | Panagiotis Kanavos | ThrowIfNotStatusOK(response, "List Containers failed"); |
145 | 5bcf6d70 | Panagiotis Kanavos | |
146 | 5bcf6d70 | Panagiotis Kanavos | |
147 | d78cbf09 | Panagiotis Kanavos | var infos=JsonConvert.DeserializeObject<IList<ContainerInfo>>(response.Content); |
148 | d78cbf09 | Panagiotis Kanavos | |
149 | d78cbf09 | Panagiotis Kanavos | return infos; |
150 | d78cbf09 | Panagiotis Kanavos | } |
151 | d78cbf09 | Panagiotis Kanavos | |
152 | d78cbf09 | Panagiotis Kanavos | public IList<ObjectInfo> ListObjects(string container) |
153 | d78cbf09 | Panagiotis Kanavos | { |
154 | d78cbf09 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(container)) |
155 | d78cbf09 | Panagiotis Kanavos | throw new ArgumentNullException("container", "The container property can't be empty"); |
156 | d78cbf09 | Panagiotis Kanavos | |
157 | b5061ac8 | Panagiotis Kanavos | Trace.TraceInformation("[START] ListObjects"); |
158 | b5061ac8 | Panagiotis Kanavos | |
159 | b5061ac8 | Panagiotis Kanavos | var request = new RestRequest { Path = container, RetryPolicy = _retryPolicy, Timeout = TimeSpan.FromMinutes(1) }; |
160 | d78cbf09 | Panagiotis Kanavos | request.AddParameter("format", "json"); |
161 | d78cbf09 | Panagiotis Kanavos | var response = _client.Request(request); |
162 | d78cbf09 | Panagiotis Kanavos | |
163 | 5bcf6d70 | Panagiotis Kanavos | var infos = InfosFromContent(response); |
164 | d78cbf09 | Panagiotis Kanavos | |
165 | b5061ac8 | Panagiotis Kanavos | Trace.TraceInformation("[END] ListObjects"); |
166 | d78cbf09 | Panagiotis Kanavos | return infos; |
167 | d78cbf09 | Panagiotis Kanavos | } |
168 | d78cbf09 | Panagiotis Kanavos | |
169 | 637bc368 | Panagiotis Kanavos | |
170 | 5bcf6d70 | Panagiotis Kanavos | |
171 | 637bc368 | Panagiotis Kanavos | public IList<ObjectInfo> ListObjects(string container,string folder) |
172 | 637bc368 | Panagiotis Kanavos | { |
173 | 637bc368 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(container)) |
174 | 637bc368 | Panagiotis Kanavos | throw new ArgumentNullException("container", "The container property can't be empty"); |
175 | 637bc368 | Panagiotis Kanavos | |
176 | b5061ac8 | Panagiotis Kanavos | Trace.TraceInformation("[START] ListObjects"); |
177 | b5061ac8 | Panagiotis Kanavos | |
178 | b5061ac8 | Panagiotis Kanavos | var request = new RestRequest { Path = container,RetryPolicy = _retryPolicy, Timeout = TimeSpan.FromMinutes(1) }; |
179 | 637bc368 | Panagiotis Kanavos | request.AddParameter("format", "json"); |
180 | 637bc368 | Panagiotis Kanavos | request.AddParameter("path", folder); |
181 | 637bc368 | Panagiotis Kanavos | var response = _client.Request(request); |
182 | 5bcf6d70 | Panagiotis Kanavos | |
183 | 5bcf6d70 | Panagiotis Kanavos | var infos = InfosFromContent(response); |
184 | 5bcf6d70 | Panagiotis Kanavos | |
185 | b5061ac8 | Panagiotis Kanavos | Trace.TraceInformation("[END] ListObjects"); |
186 | 5bcf6d70 | Panagiotis Kanavos | return infos; |
187 | 5bcf6d70 | Panagiotis Kanavos | } |
188 | 5bcf6d70 | Panagiotis Kanavos | |
189 | 5bcf6d70 | Panagiotis Kanavos | private static IList<ObjectInfo> InfosFromContent(RestResponse response) |
190 | 5bcf6d70 | Panagiotis Kanavos | { |
191 | 637bc368 | Panagiotis Kanavos | if (response.TimedOut) |
192 | 637bc368 | Panagiotis Kanavos | return new List<ObjectInfo>(); |
193 | 637bc368 | Panagiotis Kanavos | |
194 | 5bcf6d70 | Panagiotis Kanavos | if (response.StatusCode == 0) |
195 | 5bcf6d70 | Panagiotis Kanavos | return new List<ObjectInfo>(); |
196 | 637bc368 | Panagiotis Kanavos | |
197 | 637bc368 | Panagiotis Kanavos | if (response.StatusCode == HttpStatusCode.NoContent) |
198 | 637bc368 | Panagiotis Kanavos | return new List<ObjectInfo>(); |
199 | 637bc368 | Panagiotis Kanavos | |
200 | 637bc368 | Panagiotis Kanavos | |
201 | 5bcf6d70 | Panagiotis Kanavos | var statusCode = (int)response.StatusCode; |
202 | 5bcf6d70 | Panagiotis Kanavos | if (statusCode < 200 || statusCode >= 300) |
203 | 5bcf6d70 | Panagiotis Kanavos | { |
204 | 0eea575a | Panagiotis Kanavos | Trace.TraceWarning("ListObjects failed with code {0} - {1}", response.StatusCode, response.StatusDescription); |
205 | 5bcf6d70 | Panagiotis Kanavos | return new List<ObjectInfo>(); |
206 | 5bcf6d70 | Panagiotis Kanavos | } |
207 | 5bcf6d70 | Panagiotis Kanavos | |
208 | 5bcf6d70 | Panagiotis Kanavos | var infos = JsonConvert.DeserializeObject<IList<ObjectInfo>>(response.Content); |
209 | 637bc368 | Panagiotis Kanavos | return infos; |
210 | 637bc368 | Panagiotis Kanavos | } |
211 | 637bc368 | Panagiotis Kanavos | |
212 | d78cbf09 | Panagiotis Kanavos | public bool ContainerExists(string container) |
213 | d78cbf09 | Panagiotis Kanavos | { |
214 | d78cbf09 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(container)) |
215 | d78cbf09 | Panagiotis Kanavos | throw new ArgumentNullException("container", "The container property can't be empty"); |
216 | d78cbf09 | Panagiotis Kanavos | |
217 | b5061ac8 | Panagiotis Kanavos | var request = new RestRequest { Path = container, Method = WebMethod.Head, RetryPolicy = _retryPolicy,Timeout = _shortTimeout }; |
218 | d78cbf09 | Panagiotis Kanavos | var response = _client.Request(request); |
219 | d78cbf09 | Panagiotis Kanavos | |
220 | d78cbf09 | Panagiotis Kanavos | switch(response.StatusCode) |
221 | d78cbf09 | Panagiotis Kanavos | { |
222 | 3c43ec9b | Panagiotis Kanavos | case HttpStatusCode.OK: |
223 | d78cbf09 | Panagiotis Kanavos | case HttpStatusCode.NoContent: |
224 | d78cbf09 | Panagiotis Kanavos | return true; |
225 | d78cbf09 | Panagiotis Kanavos | case HttpStatusCode.NotFound: |
226 | 3c43ec9b | Panagiotis Kanavos | return false; |
227 | d78cbf09 | Panagiotis Kanavos | default: |
228 | 3c43ec9b | Panagiotis Kanavos | throw CreateWebException("ContainerExists",response.StatusCode); |
229 | d78cbf09 | Panagiotis Kanavos | } |
230 | d78cbf09 | Panagiotis Kanavos | } |
231 | d78cbf09 | Panagiotis Kanavos | |
232 | d78cbf09 | Panagiotis Kanavos | public bool ObjectExists(string container,string objectName) |
233 | d78cbf09 | Panagiotis Kanavos | { |
234 | d78cbf09 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(container)) |
235 | d78cbf09 | Panagiotis Kanavos | throw new ArgumentNullException("container", "The container property can't be empty"); |
236 | d78cbf09 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(objectName)) |
237 | d78cbf09 | Panagiotis Kanavos | throw new ArgumentNullException("objectName", "The objectName property can't be empty"); |
238 | d78cbf09 | Panagiotis Kanavos | |
239 | 5bcf6d70 | Panagiotis Kanavos | |
240 | b5061ac8 | Panagiotis Kanavos | var request = new RestRequest { Path = container + "/" + objectName, Method = WebMethod.Head,RetryPolicy = _retryPolicy, Timeout = _shortTimeout }; |
241 | d78cbf09 | Panagiotis Kanavos | var response = _client.Request(request); |
242 | d78cbf09 | Panagiotis Kanavos | |
243 | d78cbf09 | Panagiotis Kanavos | switch (response.StatusCode) |
244 | d78cbf09 | Panagiotis Kanavos | { |
245 | d78cbf09 | Panagiotis Kanavos | case HttpStatusCode.OK: |
246 | d78cbf09 | Panagiotis Kanavos | case HttpStatusCode.NoContent: |
247 | d78cbf09 | Panagiotis Kanavos | return true; |
248 | d78cbf09 | Panagiotis Kanavos | case HttpStatusCode.NotFound: |
249 | d78cbf09 | Panagiotis Kanavos | return false; |
250 | d78cbf09 | Panagiotis Kanavos | default: |
251 | 3c43ec9b | Panagiotis Kanavos | throw CreateWebException("ObjectExists",response.StatusCode); |
252 | d78cbf09 | Panagiotis Kanavos | } |
253 | d78cbf09 | Panagiotis Kanavos | |
254 | d78cbf09 | Panagiotis Kanavos | } |
255 | d78cbf09 | Panagiotis Kanavos | |
256 | d78cbf09 | Panagiotis Kanavos | public ObjectInfo GetObjectInfo(string container, string objectName) |
257 | d78cbf09 | Panagiotis Kanavos | { |
258 | d78cbf09 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(container)) |
259 | d78cbf09 | Panagiotis Kanavos | throw new ArgumentNullException("container", "The container property can't be empty"); |
260 | d78cbf09 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(objectName)) |
261 | d78cbf09 | Panagiotis Kanavos | throw new ArgumentNullException("objectName", "The objectName property can't be empty"); |
262 | d78cbf09 | Panagiotis Kanavos | |
263 | d78cbf09 | Panagiotis Kanavos | |
264 | b5061ac8 | Panagiotis Kanavos | var request = new RestRequest { Path = container + "/" + objectName, Method = WebMethod.Head, RetryPolicy = _retryPolicy,Timeout = _shortTimeout }; |
265 | d78cbf09 | Panagiotis Kanavos | var response = _client.Request(request); |
266 | d78cbf09 | Panagiotis Kanavos | |
267 | d78cbf09 | Panagiotis Kanavos | if (response.TimedOut) |
268 | d78cbf09 | Panagiotis Kanavos | return ObjectInfo.Empty; |
269 | d78cbf09 | Panagiotis Kanavos | |
270 | d78cbf09 | Panagiotis Kanavos | switch (response.StatusCode) |
271 | d78cbf09 | Panagiotis Kanavos | { |
272 | d78cbf09 | Panagiotis Kanavos | case HttpStatusCode.OK: |
273 | d78cbf09 | Panagiotis Kanavos | case HttpStatusCode.NoContent: |
274 | d78cbf09 | Panagiotis Kanavos | var keys = response.Headers.AllKeys.AsQueryable(); |
275 | 0050438e | Panagiotis Kanavos | var tags=(from key in keys |
276 | 0050438e | Panagiotis Kanavos | where key.StartsWith("X-Object-Meta-") |
277 | 0050438e | Panagiotis Kanavos | let name=key.Substring(14) |
278 | 0050438e | Panagiotis Kanavos | select new {Name=name,Value=response.Headers[name]}) |
279 | 0050438e | Panagiotis Kanavos | .ToDictionary(t=>t.Name,t=>t.Value); |
280 | 3c43ec9b | Panagiotis Kanavos | var extensions = (from key in keys |
281 | 3c43ec9b | Panagiotis Kanavos | where key.StartsWith("X-Object-") && !key.StartsWith("X-Object-Meta-") |
282 | 3c43ec9b | Panagiotis Kanavos | let name = key.Substring(9) |
283 | 3c43ec9b | Panagiotis Kanavos | select new { Name = name, Value = response.Headers[name] }) |
284 | 3c43ec9b | Panagiotis Kanavos | .ToDictionary(t => t.Name, t => t.Value); |
285 | d78cbf09 | Panagiotis Kanavos | return new ObjectInfo |
286 | d78cbf09 | Panagiotis Kanavos | { |
287 | b5061ac8 | Panagiotis Kanavos | Name = objectName, |
288 | d78cbf09 | Panagiotis Kanavos | Bytes = long.Parse(GetHeaderValue("Content-Length", response, keys)), |
289 | d78cbf09 | Panagiotis Kanavos | Hash = GetHeaderValue("ETag", response, keys), |
290 | 0050438e | Panagiotis Kanavos | Content_Type = GetHeaderValue("Content-Type", response, keys), |
291 | 3c43ec9b | Panagiotis Kanavos | Tags=tags, |
292 | 3c43ec9b | Panagiotis Kanavos | Extensions=extensions |
293 | d78cbf09 | Panagiotis Kanavos | }; |
294 | d78cbf09 | Panagiotis Kanavos | case HttpStatusCode.NotFound: |
295 | d78cbf09 | Panagiotis Kanavos | return ObjectInfo.Empty; |
296 | d78cbf09 | Panagiotis Kanavos | default: |
297 | b5061ac8 | Panagiotis Kanavos | if (request.RetryState.RepeatCount > 0) |
298 | b5061ac8 | Panagiotis Kanavos | { |
299 | b5061ac8 | Panagiotis Kanavos | Trace.TraceWarning("[RETRY FAIL] GetObjectInfo for {0} failed after {1} retries", |
300 | b5061ac8 | Panagiotis Kanavos | objectName, request.RetryState.RepeatCount); |
301 | b5061ac8 | Panagiotis Kanavos | return ObjectInfo.Empty; |
302 | b5061ac8 | Panagiotis Kanavos | } |
303 | b5061ac8 | Panagiotis Kanavos | if (response.InnerException != null) |
304 | b5061ac8 | Panagiotis Kanavos | throw new WebException(String.Format("[FAIL] GetObjectInfo for {0} failed with unexpected status code {1}", objectName, response.StatusCode), response.InnerException); |
305 | b5061ac8 | Panagiotis Kanavos | throw new WebException(String.Format("[FAIL] GetObjectInfo for {0} failed with unexpected status code {1}", objectName, response.StatusCode)); |
306 | d78cbf09 | Panagiotis Kanavos | } |
307 | d78cbf09 | Panagiotis Kanavos | } |
308 | d78cbf09 | Panagiotis Kanavos | |
309 | 10523ad9 | Panagiotis Kanavos | public void CreateFolder(string container, string folder) |
310 | 10523ad9 | Panagiotis Kanavos | { |
311 | 10523ad9 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(container)) |
312 | 10523ad9 | Panagiotis Kanavos | throw new ArgumentNullException("container", "The container property can't be empty"); |
313 | 10523ad9 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(folder)) |
314 | 10523ad9 | Panagiotis Kanavos | throw new ArgumentNullException("folder", "The folder property can't be empty"); |
315 | 10523ad9 | Panagiotis Kanavos | |
316 | 10523ad9 | Panagiotis Kanavos | var folderUrl=String.Format("{0}/{1}",container,folder); |
317 | b5061ac8 | Panagiotis Kanavos | var request = new RestRequest { Path = folderUrl, Method = WebMethod.Put, RetryPolicy = _retryPolicy,Timeout = _shortTimeout }; |
318 | 10523ad9 | Panagiotis Kanavos | request.AddHeader("Content-Type", @"application/directory"); |
319 | 10523ad9 | Panagiotis Kanavos | request.AddHeader("Content-Length", "0"); |
320 | 10523ad9 | Panagiotis Kanavos | |
321 | 10523ad9 | Panagiotis Kanavos | var response = _client.Request(request); |
322 | 10523ad9 | Panagiotis Kanavos | |
323 | 10523ad9 | Panagiotis Kanavos | if (response.StatusCode != HttpStatusCode.Created && response.StatusCode != HttpStatusCode.Accepted) |
324 | 3c43ec9b | Panagiotis Kanavos | throw CreateWebException("CreateFolder", response.StatusCode); |
325 | 10523ad9 | Panagiotis Kanavos | |
326 | 10523ad9 | Panagiotis Kanavos | } |
327 | 10523ad9 | Panagiotis Kanavos | |
328 | d78cbf09 | Panagiotis Kanavos | public ContainerInfo GetContainerInfo(string container) |
329 | d78cbf09 | Panagiotis Kanavos | { |
330 | d78cbf09 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(container)) |
331 | d78cbf09 | Panagiotis Kanavos | throw new ArgumentNullException("container", "The container property can't be empty"); |
332 | d78cbf09 | Panagiotis Kanavos | |
333 | b5061ac8 | Panagiotis Kanavos | var request = new RestRequest { Path = container, Method = WebMethod.Head, RetryPolicy = _retryPolicy,Timeout = _shortTimeout }; |
334 | d78cbf09 | Panagiotis Kanavos | var response = _client.Request(request); |
335 | d78cbf09 | Panagiotis Kanavos | |
336 | d78cbf09 | Panagiotis Kanavos | switch(response.StatusCode) |
337 | d78cbf09 | Panagiotis Kanavos | { |
338 | d78cbf09 | Panagiotis Kanavos | case HttpStatusCode.NoContent: |
339 | d78cbf09 | Panagiotis Kanavos | var keys = response.Headers.AllKeys.AsQueryable(); |
340 | d78cbf09 | Panagiotis Kanavos | var containerInfo = new ContainerInfo |
341 | d78cbf09 | Panagiotis Kanavos | { |
342 | d78cbf09 | Panagiotis Kanavos | Name = container, |
343 | d78cbf09 | Panagiotis Kanavos | Count =long.Parse(GetHeaderValue("X-Container-Object-Count", response, keys)), |
344 | d78cbf09 | Panagiotis Kanavos | Bytes =long.Parse(GetHeaderValue("X-Container-Bytes-Used", response, keys)) |
345 | d78cbf09 | Panagiotis Kanavos | }; |
346 | d78cbf09 | Panagiotis Kanavos | return containerInfo; |
347 | d78cbf09 | Panagiotis Kanavos | case HttpStatusCode.NotFound: |
348 | d78cbf09 | Panagiotis Kanavos | return ContainerInfo.Empty; |
349 | d78cbf09 | Panagiotis Kanavos | default: |
350 | 3c43ec9b | Panagiotis Kanavos | throw CreateWebException("GetContainerInfo", response.StatusCode); |
351 | d78cbf09 | Panagiotis Kanavos | } |
352 | d78cbf09 | Panagiotis Kanavos | } |
353 | d78cbf09 | Panagiotis Kanavos | |
354 | d78cbf09 | Panagiotis Kanavos | public void CreateContainer(string container) |
355 | d78cbf09 | Panagiotis Kanavos | { |
356 | d78cbf09 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(container)) |
357 | d78cbf09 | Panagiotis Kanavos | throw new ArgumentNullException("container", "The container property can't be empty"); |
358 | d78cbf09 | Panagiotis Kanavos | |
359 | b5061ac8 | Panagiotis Kanavos | var request = new RestRequest { Path = container, Method = WebMethod.Put, RetryPolicy = _retryPolicy,Timeout = _shortTimeout }; |
360 | d78cbf09 | Panagiotis Kanavos | |
361 | b6c72f62 | Panagiotis Kanavos | var response = _client.Request(request); |
362 | 3c43ec9b | Panagiotis Kanavos | |
363 | 3c43ec9b | Panagiotis Kanavos | var expectedCodes = new[]{HttpStatusCode.Created ,HttpStatusCode.Accepted , HttpStatusCode.OK}; |
364 | 3c43ec9b | Panagiotis Kanavos | if (!expectedCodes.Contains(response.StatusCode)) |
365 | 3c43ec9b | Panagiotis Kanavos | throw CreateWebException("CreateContainer", response.StatusCode); |
366 | d78cbf09 | Panagiotis Kanavos | } |
367 | d78cbf09 | Panagiotis Kanavos | |
368 | 2c053915 | Panagiotis Kanavos | public void DeleteContainer(string container) |
369 | 2c053915 | Panagiotis Kanavos | { |
370 | 2c053915 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(container)) |
371 | 2c053915 | Panagiotis Kanavos | throw new ArgumentNullException("container", "The container property can't be empty"); |
372 | 2c053915 | Panagiotis Kanavos | |
373 | b5061ac8 | Panagiotis Kanavos | var request = new RestRequest { Path = container, Method = WebMethod.Delete, RetryPolicy = _retryPolicy,Timeout = _shortTimeout }; |
374 | 2c053915 | Panagiotis Kanavos | var response = _client.Request(request); |
375 | 2c053915 | Panagiotis Kanavos | |
376 | 3c43ec9b | Panagiotis Kanavos | var expectedCodes = new[] { HttpStatusCode.NotFound, HttpStatusCode.NoContent}; |
377 | 3c43ec9b | Panagiotis Kanavos | if (!expectedCodes.Contains(response.StatusCode)) |
378 | 3c43ec9b | Panagiotis Kanavos | throw CreateWebException("DeleteContainer", response.StatusCode); |
379 | 2c053915 | Panagiotis Kanavos | |
380 | 2c053915 | Panagiotis Kanavos | } |
381 | 2c053915 | Panagiotis Kanavos | |
382 | 5bcf6d70 | Panagiotis Kanavos | /// <summary> |
383 | 5bcf6d70 | Panagiotis Kanavos | /// |
384 | 5bcf6d70 | Panagiotis Kanavos | /// </summary> |
385 | 5bcf6d70 | Panagiotis Kanavos | /// <param name="container"></param> |
386 | 5bcf6d70 | Panagiotis Kanavos | /// <param name="objectName"></param> |
387 | 283809f3 | Panagiotis Kanavos | /// <param name="fileName"></param> |
388 | 5bcf6d70 | Panagiotis Kanavos | /// <returns></returns> |
389 | 5bcf6d70 | Panagiotis Kanavos | /// <remarks>>This method should have no timeout or a very long one</remarks> |
390 | 283809f3 | Panagiotis Kanavos | public Task GetObject(string container, string objectName, string fileName) |
391 | d78cbf09 | Panagiotis Kanavos | { |
392 | d78cbf09 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(container)) |
393 | d78cbf09 | Panagiotis Kanavos | throw new ArgumentNullException("container", "The container property can't be empty"); |
394 | d78cbf09 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(objectName)) |
395 | d78cbf09 | Panagiotis Kanavos | throw new ArgumentNullException("objectName", "The objectName property can't be empty"); |
396 | d78cbf09 | Panagiotis Kanavos | |
397 | 283809f3 | Panagiotis Kanavos | var request = new RestRequest {Path = container + "/" + objectName, Method = WebMethod.Get}; |
398 | 283809f3 | Panagiotis Kanavos | /* |
399 | 283809f3 | Panagiotis Kanavos | if (DownloadPercentLimit > 0) |
400 | 283809f3 | Panagiotis Kanavos | request.TaskOptions = new TaskOptions<int> { RateLimitPercent = DownloadPercentLimit }; |
401 | 283809f3 | Panagiotis Kanavos | */ |
402 | 283809f3 | Panagiotis Kanavos | try |
403 | 283809f3 | Panagiotis Kanavos | { |
404 | 283809f3 | Panagiotis Kanavos | var url = String.Join("/", new[] {_client.Authority, container, objectName}); |
405 | 283809f3 | Panagiotis Kanavos | var uri = new Uri(url); |
406 | 283809f3 | Panagiotis Kanavos | |
407 | 283809f3 | Panagiotis Kanavos | var client = new WebClient(); |
408 | 283809f3 | Panagiotis Kanavos | if (!String.IsNullOrWhiteSpace(_client.Proxy)) |
409 | 283809f3 | Panagiotis Kanavos | client.Proxy = new WebProxy(_client.Proxy); |
410 | 283809f3 | Panagiotis Kanavos | |
411 | 283809f3 | Panagiotis Kanavos | CopyHeaders(_client, client); |
412 | 283809f3 | Panagiotis Kanavos | |
413 | 283809f3 | Panagiotis Kanavos | Trace.TraceInformation("[GET] START {0}", objectName); |
414 | 283809f3 | Panagiotis Kanavos | client.DownloadProgressChanged += (sender, args) => |
415 | 283809f3 | Panagiotis Kanavos | Trace.TraceInformation("[GET PROGRESS] {0} {1}% {2} of {3}", |
416 | 283809f3 | Panagiotis Kanavos | fileName, args.ProgressPercentage, |
417 | 283809f3 | Panagiotis Kanavos | args.BytesReceived, |
418 | 283809f3 | Panagiotis Kanavos | args.TotalBytesToReceive); |
419 | 283809f3 | Panagiotis Kanavos | |
420 | 283809f3 | Panagiotis Kanavos | return client.DownloadFileTask(uri, fileName) |
421 | 283809f3 | Panagiotis Kanavos | .ContinueWith(download => |
422 | 283809f3 | Panagiotis Kanavos | { |
423 | 283809f3 | Panagiotis Kanavos | client.Dispose(); |
424 | 283809f3 | Panagiotis Kanavos | |
425 | 283809f3 | Panagiotis Kanavos | if (download.IsFaulted) |
426 | 283809f3 | Panagiotis Kanavos | { |
427 | 283809f3 | Panagiotis Kanavos | Trace.TraceError("[GET] FAIL for {0} with \r{1}", objectName, |
428 | 283809f3 | Panagiotis Kanavos | download.Exception); |
429 | 283809f3 | Panagiotis Kanavos | } |
430 | 283809f3 | Panagiotis Kanavos | else |
431 | 283809f3 | Panagiotis Kanavos | { |
432 | 283809f3 | Panagiotis Kanavos | Trace.TraceInformation("[GET] END {0}", objectName); |
433 | 283809f3 | Panagiotis Kanavos | } |
434 | 283809f3 | Panagiotis Kanavos | }); |
435 | 283809f3 | Panagiotis Kanavos | } |
436 | 283809f3 | Panagiotis Kanavos | catch (Exception exc) |
437 | d78cbf09 | Panagiotis Kanavos | { |
438 | 283809f3 | Panagiotis Kanavos | Trace.TraceError("[GET] END {0} with {1}", objectName, exc); |
439 | 283809f3 | Panagiotis Kanavos | throw; |
440 | d78cbf09 | Panagiotis Kanavos | } |
441 | 283809f3 | Panagiotis Kanavos | |
442 | 283809f3 | Panagiotis Kanavos | |
443 | 283809f3 | Panagiotis Kanavos | |
444 | d78cbf09 | Panagiotis Kanavos | } |
445 | d78cbf09 | Panagiotis Kanavos | |
446 | 5bcf6d70 | Panagiotis Kanavos | /// <summary> |
447 | 5bcf6d70 | Panagiotis Kanavos | /// |
448 | 5bcf6d70 | Panagiotis Kanavos | /// </summary> |
449 | 5bcf6d70 | Panagiotis Kanavos | /// <param name="container"></param> |
450 | 5bcf6d70 | Panagiotis Kanavos | /// <param name="objectName"></param> |
451 | 5bcf6d70 | Panagiotis Kanavos | /// <param name="fileName"></param> |
452 | b5061ac8 | Panagiotis Kanavos | /// <param name="hash">Optional hash value for the file. If no hash is provided, the method calculates a new hash</param> |
453 | 5bcf6d70 | Panagiotis Kanavos | /// <remarks>>This method should have no timeout or a very long one</remarks> |
454 | b5061ac8 | Panagiotis Kanavos | public Task PutObject(string container, string objectName, string fileName, string hash = null) |
455 | d78cbf09 | Panagiotis Kanavos | { |
456 | d78cbf09 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(container)) |
457 | d78cbf09 | Panagiotis Kanavos | throw new ArgumentNullException("container", "The container property can't be empty"); |
458 | d78cbf09 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(objectName)) |
459 | d78cbf09 | Panagiotis Kanavos | throw new ArgumentNullException("objectName", "The objectName property can't be empty"); |
460 | b6c72f62 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(fileName)) |
461 | b6c72f62 | Panagiotis Kanavos | throw new ArgumentNullException("fileName", "The fileName property can't be empty"); |
462 | 637bc368 | Panagiotis Kanavos | if (!File.Exists(fileName)) |
463 | 637bc368 | Panagiotis Kanavos | throw new FileNotFoundException("The file does not exist",fileName); |
464 | d78cbf09 | Panagiotis Kanavos | |
465 | b6c72f62 | Panagiotis Kanavos | |
466 | b5061ac8 | Panagiotis Kanavos | try |
467 | b5061ac8 | Panagiotis Kanavos | { |
468 | 0eea575a | Panagiotis Kanavos | var url = String.Join("/",new[]{_client.Authority,container,objectName}); |
469 | 0eea575a | Panagiotis Kanavos | var uri = new Uri(url); |
470 | 0eea575a | Panagiotis Kanavos | |
471 | 0eea575a | Panagiotis Kanavos | var client = new WebClient(); |
472 | 0eea575a | Panagiotis Kanavos | string etag = hash ?? CalculateHash(fileName); |
473 | 0eea575a | Panagiotis Kanavos | |
474 | 0eea575a | Panagiotis Kanavos | client.Headers.Add("Content-Type", "application/octet-stream"); |
475 | 0eea575a | Panagiotis Kanavos | client.Headers.Add("ETag", etag); |
476 | 0eea575a | Panagiotis Kanavos | |
477 | 0eea575a | Panagiotis Kanavos | if(!String.IsNullOrWhiteSpace(_client.Proxy)) |
478 | 0eea575a | Panagiotis Kanavos | client.Proxy = new WebProxy(_client.Proxy); |
479 | 0eea575a | Panagiotis Kanavos | |
480 | 0eea575a | Panagiotis Kanavos | CopyHeaders(_client, client); |
481 | 0eea575a | Panagiotis Kanavos | |
482 | 0eea575a | Panagiotis Kanavos | Trace.TraceInformation("[PUT] START {0}", objectName); |
483 | 0eea575a | Panagiotis Kanavos | client.UploadProgressChanged += (sender, args) => |
484 | 0eea575a | Panagiotis Kanavos | { |
485 | 283809f3 | Panagiotis Kanavos | Trace.TraceInformation("[PUT PROGRESS] {0} {1}% {2} of {3}", fileName, args.ProgressPercentage, args.BytesSent, args.TotalBytesToSend); |
486 | 0eea575a | Panagiotis Kanavos | }; |
487 | 0eea575a | Panagiotis Kanavos | |
488 | 0eea575a | Panagiotis Kanavos | return client.UploadFileTask(uri, "PUT", fileName) |
489 | 0eea575a | Panagiotis Kanavos | .ContinueWith(upload=> |
490 | 0eea575a | Panagiotis Kanavos | { |
491 | 0eea575a | Panagiotis Kanavos | client.Dispose(); |
492 | 0eea575a | Panagiotis Kanavos | |
493 | 0eea575a | Panagiotis Kanavos | if (upload.IsFaulted) |
494 | 0eea575a | Panagiotis Kanavos | { |
495 | 0eea575a | Panagiotis Kanavos | Trace.TraceError("[PUT] FAIL for {0} with \r{1}",objectName,upload.Exception); |
496 | 0eea575a | Panagiotis Kanavos | } |
497 | 0eea575a | Panagiotis Kanavos | else |
498 | 0eea575a | Panagiotis Kanavos | Trace.TraceInformation("[PUT] END {0}", objectName); |
499 | 0eea575a | Panagiotis Kanavos | }); |
500 | b5061ac8 | Panagiotis Kanavos | } |
501 | b5061ac8 | Panagiotis Kanavos | catch (Exception exc) |
502 | b5061ac8 | Panagiotis Kanavos | { |
503 | b5061ac8 | Panagiotis Kanavos | Trace.TraceError("[PUT] END {0} with {1}", objectName, exc); |
504 | b5061ac8 | Panagiotis Kanavos | throw; |
505 | b5061ac8 | Panagiotis Kanavos | } |
506 | b5061ac8 | Panagiotis Kanavos | |
507 | 0eea575a | Panagiotis Kanavos | } |
508 | 0050438e | Panagiotis Kanavos | |
509 | 0eea575a | Panagiotis Kanavos | |
510 | 0eea575a | Panagiotis Kanavos | /// <summary> |
511 | 0eea575a | Panagiotis Kanavos | /// Copies headers from a Hammock RestClient to a WebClient |
512 | 0eea575a | Panagiotis Kanavos | /// </summary> |
513 | 0eea575a | Panagiotis Kanavos | /// <param name="source">The RestClient from which the headers are copied</param> |
514 | 0eea575a | Panagiotis Kanavos | /// <param name="target">The WebClient to which the headers are copied</param> |
515 | 0eea575a | Panagiotis Kanavos | private static void CopyHeaders(RestClient source, WebClient target) |
516 | 0eea575a | Panagiotis Kanavos | { |
517 | 0eea575a | Panagiotis Kanavos | Contract.Requires(source!=null,"source can't be null"); |
518 | 0eea575a | Panagiotis Kanavos | Contract.Requires(target != null, "target can't be null"); |
519 | 0eea575a | Panagiotis Kanavos | if (source == null) |
520 | 0eea575a | Panagiotis Kanavos | throw new ArgumentNullException("source", "source can't be null"); |
521 | 0eea575a | Panagiotis Kanavos | if (source == null) |
522 | 0eea575a | Panagiotis Kanavos | throw new ArgumentNullException("target", "target can't be null"); |
523 | 0eea575a | Panagiotis Kanavos | |
524 | 0eea575a | Panagiotis Kanavos | foreach (var header in source.GetAllHeaders()) |
525 | 0eea575a | Panagiotis Kanavos | { |
526 | 0eea575a | Panagiotis Kanavos | target.Headers.Add(header.Name, header.Value); |
527 | 0eea575a | Panagiotis Kanavos | } |
528 | d78cbf09 | Panagiotis Kanavos | } |
529 | d78cbf09 | Panagiotis Kanavos | |
530 | b6c72f62 | Panagiotis Kanavos | private static string CalculateHash(string fileName) |
531 | d78cbf09 | Panagiotis Kanavos | { |
532 | d78cbf09 | Panagiotis Kanavos | string hash; |
533 | d78cbf09 | Panagiotis Kanavos | using (var hasher = MD5.Create()) |
534 | b6c72f62 | Panagiotis Kanavos | using(var stream=File.OpenRead(fileName)) |
535 | d78cbf09 | Panagiotis Kanavos | { |
536 | d78cbf09 | Panagiotis Kanavos | var hashBuilder=new StringBuilder(); |
537 | b6c72f62 | Panagiotis Kanavos | foreach (byte b in hasher.ComputeHash(stream)) |
538 | d78cbf09 | Panagiotis Kanavos | hashBuilder.Append(b.ToString("x2").ToLower()); |
539 | d78cbf09 | Panagiotis Kanavos | hash = hashBuilder.ToString(); |
540 | d78cbf09 | Panagiotis Kanavos | } |
541 | d78cbf09 | Panagiotis Kanavos | return hash; |
542 | d78cbf09 | Panagiotis Kanavos | } |
543 | d78cbf09 | Panagiotis Kanavos | |
544 | d78cbf09 | Panagiotis Kanavos | public void DeleteObject(string container, string objectName) |
545 | d78cbf09 | Panagiotis Kanavos | { |
546 | d78cbf09 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(container)) |
547 | d78cbf09 | Panagiotis Kanavos | throw new ArgumentNullException("container", "The container property can't be empty"); |
548 | d78cbf09 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(objectName)) |
549 | d78cbf09 | Panagiotis Kanavos | throw new ArgumentNullException("objectName", "The objectName property can't be empty"); |
550 | d78cbf09 | Panagiotis Kanavos | |
551 | b5061ac8 | Panagiotis Kanavos | var request = new RestRequest { Path = container + "/" + objectName, Method = WebMethod.Delete, RetryPolicy = _retryPolicy,Timeout = _shortTimeout }; |
552 | d78cbf09 | Panagiotis Kanavos | var response = _client.Request(request); |
553 | d78cbf09 | Panagiotis Kanavos | |
554 | 3c43ec9b | Panagiotis Kanavos | var expectedCodes = new[] { HttpStatusCode.NotFound, HttpStatusCode.NoContent }; |
555 | 3c43ec9b | Panagiotis Kanavos | if (!expectedCodes.Contains(response.StatusCode)) |
556 | 3c43ec9b | Panagiotis Kanavos | throw CreateWebException("DeleteObject", response.StatusCode); |
557 | d78cbf09 | Panagiotis Kanavos | |
558 | d78cbf09 | Panagiotis Kanavos | } |
559 | d78cbf09 | Panagiotis Kanavos | |
560 | 3c43ec9b | Panagiotis Kanavos | public void MoveObject(string sourceContainer, string oldObjectName, string targetContainer,string newObjectName) |
561 | d78cbf09 | Panagiotis Kanavos | { |
562 | 3c43ec9b | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(sourceContainer)) |
563 | 3c43ec9b | Panagiotis Kanavos | throw new ArgumentNullException("sourceContainer", "The container property can't be empty"); |
564 | d78cbf09 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(oldObjectName)) |
565 | d78cbf09 | Panagiotis Kanavos | throw new ArgumentNullException("oldObjectName", "The oldObjectName property can't be empty"); |
566 | 3c43ec9b | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(targetContainer)) |
567 | 3c43ec9b | Panagiotis Kanavos | throw new ArgumentNullException("targetContainer", "The container property can't be empty"); |
568 | d78cbf09 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(newObjectName)) |
569 | d78cbf09 | Panagiotis Kanavos | throw new ArgumentNullException("newObjectName", "The newObjectName property can't be empty"); |
570 | d78cbf09 | Panagiotis Kanavos | |
571 | 3c43ec9b | Panagiotis Kanavos | var targetUrl = targetContainer + "/" + newObjectName; |
572 | 3c43ec9b | Panagiotis Kanavos | var sourceUrl = String.Format("/{0}/{1}", sourceContainer, oldObjectName); |
573 | 3c43ec9b | Panagiotis Kanavos | |
574 | 3c43ec9b | Panagiotis Kanavos | var request = new RestRequest { Path = targetUrl, Method = WebMethod.Put }; |
575 | 3c43ec9b | Panagiotis Kanavos | request.AddHeader("X-Copy-From",sourceUrl); |
576 | d78cbf09 | Panagiotis Kanavos | request.AddPostContent(new byte[]{}); |
577 | d78cbf09 | Panagiotis Kanavos | var response = _client.Request(request); |
578 | d78cbf09 | Panagiotis Kanavos | |
579 | 3c43ec9b | Panagiotis Kanavos | |
580 | 3c43ec9b | Panagiotis Kanavos | var expectedCodes = new[] { HttpStatusCode.OK ,HttpStatusCode.NoContent ,HttpStatusCode.Created }; |
581 | 3c43ec9b | Panagiotis Kanavos | if (expectedCodes.Contains(response.StatusCode)) |
582 | d78cbf09 | Panagiotis Kanavos | { |
583 | 3c43ec9b | Panagiotis Kanavos | this.DeleteObject(sourceContainer,oldObjectName); |
584 | d78cbf09 | Panagiotis Kanavos | } |
585 | d78cbf09 | Panagiotis Kanavos | else |
586 | 3c43ec9b | Panagiotis Kanavos | throw CreateWebException("MoveObject", response.StatusCode); |
587 | d78cbf09 | Panagiotis Kanavos | } |
588 | d78cbf09 | Panagiotis Kanavos | |
589 | d78cbf09 | Panagiotis Kanavos | private string GetHeaderValue(string headerName, RestResponse response, IQueryable<string> keys) |
590 | d78cbf09 | Panagiotis Kanavos | { |
591 | d78cbf09 | Panagiotis Kanavos | if (keys.Any(key => key == headerName)) |
592 | d78cbf09 | Panagiotis Kanavos | return response.Headers[headerName]; |
593 | d78cbf09 | Panagiotis Kanavos | else |
594 | d78cbf09 | Panagiotis Kanavos | throw new WebException(String.Format("The {0} header is missing",headerName)); |
595 | d78cbf09 | Panagiotis Kanavos | } |
596 | d78cbf09 | Panagiotis Kanavos | |
597 | d78cbf09 | Panagiotis Kanavos | private static void ThrowIfNotStatusOK(RestResponse response, string message) |
598 | d78cbf09 | Panagiotis Kanavos | { |
599 | d78cbf09 | Panagiotis Kanavos | int status = (int)response.StatusCode; |
600 | d78cbf09 | Panagiotis Kanavos | if (status < 200 || status >= 300) |
601 | d78cbf09 | Panagiotis Kanavos | throw new WebException(String.Format("{0} with code {1}",message, status)); |
602 | d78cbf09 | Panagiotis Kanavos | } |
603 | 3c43ec9b | Panagiotis Kanavos | |
604 | 3c43ec9b | Panagiotis Kanavos | private static WebException CreateWebException(string operation, HttpStatusCode statusCode) |
605 | 3c43ec9b | Panagiotis Kanavos | { |
606 | 3c43ec9b | Panagiotis Kanavos | return new WebException(String.Format("{0} failed with unexpected status code {1}", operation, statusCode)); |
607 | 3c43ec9b | Panagiotis Kanavos | } |
608 | 3c43ec9b | Panagiotis Kanavos | |
609 | d78cbf09 | Panagiotis Kanavos | } |
610 | d78cbf09 | Panagiotis Kanavos | } |