2 using System.Collections.Generic;
\r
3 using System.ComponentModel;
\r
4 using System.Diagnostics.Contracts;
\r
9 using System.Threading;
\r
10 using System.Threading.Tasks;
\r
13 namespace Pithos.Network
\r
15 public static class WebExtensions
\r
17 public static string ReadToEnd(this HttpWebResponse response)
\r
19 using (var stream = response.GetResponseStream())
\r
23 using (var reader = new StreamReader(stream))
\r
25 var body = reader.ReadToEnd();
\r
31 public static void LogError(this ILog log, HttpWebResponse response)
\r
33 if (log.IsDebugEnabled)
\r
35 if (response != null)
\r
37 var body = response.ReadToEnd();
\r
38 log.ErrorFormat("Headers:\n{0}\nBody:{1}", response.Headers, body);
\r
43 public static TextReader GetLoggedReader(this Stream stream, ILog log)
\r
45 var reader = new StreamReader(stream);
\r
46 if (!log.IsDebugEnabled)
\r
51 var body = reader.ReadToEnd();
\r
52 log.DebugFormat("JSON response: {0}", body);
\r
53 return new StringReader(body);
\r
58 public static IEnumerable<T> Range<T>(this IList<T> list, int start, int end)
\r
60 Contract.Requires(start >= 0);
\r
61 Contract.Requires(end < list.Count);
\r
62 Contract.Requires(start <= end);
\r
67 for (var i = 0; i <= end; i++)
\r
69 yield return list[i];
\r
74 public static Task<byte[]> UploadDataTaskAsync(this WebClient webClient, Uri address, string method, byte[] data, CancellationToken cancellationToken, IProgress<UploadProgressChangedEventArgs> progress)
\r
76 var tcs = new TaskCompletionSource<byte[]>(address);
\r
77 if (cancellationToken.IsCancellationRequested)
\r
79 tcs.TrySetCanceled();
\r
83 CancellationTokenRegistration ctr = cancellationToken.Register(()=>
\r
85 webClient.CancelAsync();
\r
87 UploadDataCompletedEventHandler completedHandler = null;
\r
88 UploadProgressChangedEventHandler progressHandler = null;
\r
89 if (progress != null)
\r
90 progressHandler = (s, e) => PithosEAPCommon.HandleProgress(tcs, e, () => e, progress);
\r
91 completedHandler =(sender, e) =>PithosEAPCommon.HandleCompletion(tcs, true, e,() => e.Result,() =>
\r
94 webClient.UploadDataCompleted -= completedHandler;
\r
95 webClient.UploadProgressChanged -= progressHandler;
\r
97 webClient.UploadDataCompleted += completedHandler;
\r
98 webClient.UploadProgressChanged += progressHandler;
\r
101 webClient.UploadDataAsync(address, method, data, tcs);
\r
102 if (cancellationToken.IsCancellationRequested)
\r
103 webClient.CancelAsync();
\r
107 webClient.UploadDataCompleted -= completedHandler;
\r
108 webClient.UploadProgressChanged -= progressHandler;
\r
115 public static async Task<T> WithRetries<T>(this Func<Task<T>> func, int retries)
\r
117 while (retries > 0)
\r
121 var result = await func();
\r
124 catch (Exception exc)
\r
126 if (--retries == 0)
\r
127 throw new RetryException("Failed too many times", exc);
\r
130 throw new RetryException();
\r
135 internal static class PithosEAPCommon
\r
137 internal static void HandleProgress<T, E>(TaskCompletionSource<T> tcs, ProgressChangedEventArgs eventArgs, Func<E> getProgress, IProgress<E> callback)
\r
139 if (eventArgs.UserState != tcs)
\r
141 callback.Report(getProgress());
\r
144 internal static void HandleCompletion<T>(TaskCompletionSource<T> tcs, bool requireMatch, AsyncCompletedEventArgs e, Func<T> getResult, Action unregisterHandler)
\r
148 if (e.UserState != tcs)
\r
153 unregisterHandler();
\r
158 tcs.TrySetCanceled();
\r
159 else if (e.Error != null)
\r
160 tcs.TrySetException(e.Error);
\r
162 tcs.TrySetResult(getResult());
\r