Revision 0eea575a trunk/Pithos.Network/CloudFilesClient.cs
b/trunk/Pithos.Network/CloudFilesClient.cs | ||
---|---|---|
24 | 24 |
public class CloudFilesClient:ICloudClient |
25 | 25 |
{ |
26 | 26 |
string _rackSpaceAuthUrl = "https://auth.api.rackspacecloud.com"; |
27 |
private string _pithosAuthUrl = "http://pithos.dev.grnet.gr";
|
|
27 |
private string _pithosAuthUrl = "https://pithos.grnet.gr";
|
|
28 | 28 |
|
29 | 29 |
private RestClient _client; |
30 | 30 |
private readonly TimeSpan _shortTimeout = TimeSpan.FromSeconds(10); |
... | ... | |
53 | 53 |
|
54 | 54 |
public void Authenticate(string userName,string apiKey) |
55 | 55 |
{ |
56 |
Trace.TraceInformation("[AUTHENTICATE] Start for {0}",userName); |
|
56 |
Trace.TraceInformation("[AUTHENTICATE] Start for {0}", userName);
|
|
57 | 57 |
if (String.IsNullOrWhiteSpace(userName)) |
58 |
throw new ArgumentNullException("userName","The userName property can't be empty"); |
|
58 |
throw new ArgumentNullException("userName", "The userName property can't be empty");
|
|
59 | 59 |
if (String.IsNullOrWhiteSpace(apiKey)) |
60 | 60 |
throw new ArgumentNullException("apiKey", "The apiKey property can't be empty"); |
61 |
|
|
62 | 61 |
|
63 | 62 |
UserName = userName; |
64 | 63 |
ApiKey = apiKey; |
65 |
|
|
66 |
string authUrl = UsePithos ? String.Format("{0}/{1}/{2}", AuthUrl, VersionPath,UserName) |
|
67 |
: String.Format("{0}/{1}", AuthUrl, VersionPath); |
|
68 |
|
|
69 |
var proxy = Proxy != null ? Proxy.ToString():null; |
|
70 |
|
|
71 |
var authClient = new RestClient{Path=authUrl,Proxy=proxy}; |
|
72 |
|
|
73 |
authClient.AddHeader("X-Auth-User", UserName); |
|
74 |
authClient.AddHeader("X-Auth-Key", ApiKey); |
|
75 | 64 |
|
76 |
var response=authClient.Request(); |
|
77 |
|
|
78 |
ThrowIfNotStatusOK(response, "Authentication failed"); |
|
65 |
var proxy = Proxy != null ? Proxy.ToString() : null; |
|
66 |
if (UsePithos) |
|
67 |
{ |
|
68 |
Token = "0000"; |
|
69 |
string storageUrl = String.Format("{0}/{1}/{2}", AuthUrl, VersionPath, UserName); |
|
70 |
StorageUrl = new Uri(storageUrl); |
|
71 |
} |
|
72 |
else |
|
73 |
{ |
|
79 | 74 |
|
80 |
var keys = response.Headers.AllKeys.AsQueryable(); |
|
75 |
string authUrl = String.Format("{0}/{1}", AuthUrl, VersionPath); |
|
76 |
var authClient = new RestClient {Path = authUrl, Proxy = proxy}; |
|
81 | 77 |
|
82 |
string storageUrl =UsePithos? |
|
83 |
String.Format("{0}/{1}/{2}",AuthUrl,VersionPath,UserName) |
|
84 |
:GetHeaderValue("X-Storage-Url", response, keys); |
|
85 |
|
|
86 |
if (String.IsNullOrWhiteSpace(storageUrl)) |
|
87 |
throw new InvalidOperationException("Failed to obtain storage url"); |
|
88 |
StorageUrl = new Uri(storageUrl); |
|
78 |
authClient.AddHeader("X-Auth-User", UserName); |
|
79 |
authClient.AddHeader("X-Auth-Key", ApiKey); |
|
80 |
|
|
81 |
var response = authClient.Request(); |
|
82 |
|
|
83 |
ThrowIfNotStatusOK(response, "Authentication failed"); |
|
84 |
|
|
85 |
var keys = response.Headers.AllKeys.AsQueryable(); |
|
86 |
|
|
87 |
string storageUrl = GetHeaderValue("X-Storage-Url", response, keys); |
|
88 |
if (String.IsNullOrWhiteSpace(storageUrl)) |
|
89 |
throw new InvalidOperationException("Failed to obtain storage url"); |
|
90 |
StorageUrl = new Uri(storageUrl); |
|
89 | 91 |
|
90 |
if (!UsePithos) |
|
91 |
{ |
|
92 | 92 |
var token = GetHeaderValue("X-Auth-Token", response, keys); |
93 | 93 |
if (String.IsNullOrWhiteSpace(token)) |
94 | 94 |
throw new InvalidOperationException("Failed to obtain token url"); |
95 | 95 |
Token = token; |
96 | 96 |
} |
97 |
else |
|
98 |
Token = "0000"; |
|
99 | 97 |
|
100 | 98 |
_retryPolicy = new RetryPolicy { RetryCount = _retries }; |
101 | 99 |
_retryPolicy.RetryConditions.Add(new TimeoutRetryCondition()); |
... | ... | |
104 | 102 |
_client.FileProgress += OnFileProgress; |
105 | 103 |
|
106 | 104 |
_client.AddHeader("X-Auth-Token", Token); |
107 |
if (UsePithos) |
|
105 |
/*if (UsePithos)
|
|
108 | 106 |
{ |
109 | 107 |
_client.AddHeader("X-Auth-User", UserName); |
110 | 108 |
_client.AddHeader("X-Auth-Key",ApiKey); |
111 |
} |
|
109 |
}*/
|
|
112 | 110 |
|
113 | 111 |
Trace.TraceInformation("[AUTHENTICATE] End for {0}", userName); |
114 | 112 |
} |
... | ... | |
198 | 196 |
var statusCode = (int)response.StatusCode; |
199 | 197 |
if (statusCode < 200 || statusCode >= 300) |
200 | 198 |
{ |
201 |
Trace.TraceWarning("ListObjects failed with code {1} - {2}", response.StatusCode, response.StatusDescription);
|
|
199 |
Trace.TraceWarning("ListObjects failed with code {0} - {1}", response.StatusCode, response.StatusDescription);
|
|
202 | 200 |
return new List<ObjectInfo>(); |
203 | 201 |
} |
204 | 202 |
|
... | ... | |
414 | 412 |
if (!File.Exists(fileName)) |
415 | 413 |
throw new FileNotFoundException("The file does not exist",fileName); |
416 | 414 |
|
417 |
|
|
418 |
string url = container + "/" + objectName; |
|
419 |
|
|
420 |
var request = new RestRequest {Path=url,Method=WebMethod.Put}; |
|
421 | 415 |
|
422 |
/* |
|
423 |
if(UploadPercentLimit>0) |
|
424 |
request.TaskOptions=new TaskOptions<int>{RateLimitPercent=UploadPercentLimit}; |
|
425 |
*/ |
|
426 |
Trace.TraceInformation("[PUT] START {0}",objectName); |
|
427 |
string etag = hash??CalculateHash(fileName); |
|
428 |
request.AddFile(fileName, fileName, fileName); |
|
429 |
//request.AddPostContent(File.ReadAllBytes(fileName)); |
|
430 |
request.AddHeader("Content-Type","application/octet-stream"); |
|
431 |
request.AddHeader("ETag", etag); |
|
432 |
//_client.TaskOptions = new TaskOptions<int> {RateLimitPercent = 0.5}; |
|
433 | 416 |
try |
434 | 417 |
{ |
435 |
|
|
436 |
var response=_client.Request(request); |
|
437 |
Trace.TraceInformation("[PUT] END {0}", objectName); |
|
438 |
|
|
439 |
if (response.StatusCode == HttpStatusCode.Created) |
|
440 |
return Task.Factory.StartNew(()=>{}); |
|
441 |
if (response.StatusCode == HttpStatusCode.LengthRequired) |
|
442 |
throw new InvalidOperationException(); |
|
443 |
else |
|
444 |
throw new WebException(String.Format("GetObject failed with unexpected status code {0}", |
|
445 |
response.StatusCode)); |
|
446 |
/* return Task.Factory.FromAsync(_client.BeginRequest(request),ar=>_client.EndRequest(ar)) |
|
447 |
.ContinueWith(t=> |
|
448 |
{*/ |
|
418 |
var url = String.Join("/",new[]{_client.Authority,container,objectName}); |
|
419 |
var uri = new Uri(url); |
|
420 |
|
|
421 |
var client = new WebClient(); |
|
422 |
string etag = hash ?? CalculateHash(fileName); |
|
423 |
|
|
424 |
client.Headers.Add("Content-Type", "application/octet-stream"); |
|
425 |
client.Headers.Add("ETag", etag); |
|
426 |
|
|
427 |
if(!String.IsNullOrWhiteSpace(_client.Proxy)) |
|
428 |
client.Proxy = new WebProxy(_client.Proxy); |
|
429 |
|
|
430 |
CopyHeaders(_client, client); |
|
431 |
|
|
432 |
Trace.TraceInformation("[PUT] START {0}", objectName); |
|
433 |
client.UploadProgressChanged += (sender, args) => |
|
434 |
{ |
|
435 |
Trace.TraceInformation("[PROGRESS] {0} {1}% {2} of {3}", fileName, args.ProgressPercentage, args.BytesSent, args.TotalBytesToSend); |
|
436 |
}; |
|
437 |
|
|
438 |
return client.UploadFileTask(uri, "PUT", fileName) |
|
439 |
.ContinueWith(upload=> |
|
440 |
{ |
|
441 |
client.Dispose(); |
|
442 |
|
|
443 |
if (upload.IsFaulted) |
|
444 |
{ |
|
445 |
Trace.TraceError("[PUT] FAIL for {0} with \r{1}",objectName,upload.Exception); |
|
446 |
} |
|
447 |
else |
|
448 |
Trace.TraceInformation("[PUT] END {0}", objectName); |
|
449 |
}); |
|
449 | 450 |
} |
450 | 451 |
catch (Exception exc) |
451 | 452 |
{ |
... | ... | |
453 | 454 |
throw; |
454 | 455 |
} |
455 | 456 |
|
456 |
/* |
|
457 |
var response = t.Result; |
|
458 |
if (t.IsFaulted) |
|
459 |
Trace.TraceError("[PUT] END {0} with {1}", objectName, t.Exception); |
|
460 |
else |
|
461 |
{ |
|
462 |
Trace.TraceInformation("[PUT] END {0}",objectName); |
|
463 |
} |
|
464 |
*/ |
|
465 |
/* if (response.StatusCode == HttpStatusCode.Created) |
|
466 |
return; |
|
467 |
if (response.StatusCode == HttpStatusCode.LengthRequired) |
|
468 |
throw new InvalidOperationException(); |
|
469 |
else |
|
470 |
throw new WebException(String.Format("GetObject failed with unexpected status code {0}", |
|
471 |
response.StatusCode));*/ |
|
472 |
/*});*/ |
|
457 |
} |
|
458 |
|
|
459 |
/// <summary> |
|
460 |
/// Copies headers from a Hammock RestClient to a WebClient |
|
461 |
/// </summary> |
|
462 |
/// <param name="source">The RestClient from which the headers are copied</param> |
|
463 |
/// <param name="target">The WebClient to which the headers are copied</param> |
|
464 |
private static void CopyHeaders(RestClient source, WebClient target) |
|
465 |
{ |
|
466 |
Contract.Requires(source!=null,"source can't be null"); |
|
467 |
Contract.Requires(target != null, "target can't be null"); |
|
468 |
if (source == null) |
|
469 |
throw new ArgumentNullException("source", "source can't be null"); |
|
470 |
if (source == null) |
|
471 |
throw new ArgumentNullException("target", "target can't be null"); |
|
472 |
|
|
473 |
foreach (var header in source.GetAllHeaders()) |
|
474 |
{ |
|
475 |
target.Headers.Add(header.Name, header.Value); |
|
476 |
} |
|
473 | 477 |
} |
474 | 478 |
|
475 | 479 |
private static string CalculateHash(string fileName) |
Also available in: Unified diff