2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Diagnostics.Contracts;
9 using System.Threading;
10 using System.Threading.Tasks;
13 namespace Pithos.Network
15 public static class WebExtensions
18 public static string ReadToEnd(this HttpWebResponse response)
20 using (var stream = response.GetResponseStream())
24 using (var reader = new StreamReader(stream))
26 var body = reader.ReadToEnd();
32 public static void LogError(this ILog log, HttpWebResponse response)
34 if (log.IsDebugEnabled)
38 var body = response.ReadToEnd();
39 log.ErrorFormat("Headers:\n{0}\nBody:{1}", response.Headers, body);
44 public static TextReader GetLoggedReader(this Stream stream, ILog log)
46 var reader = new StreamReader(stream);
47 if (!log.IsDebugEnabled)
52 var body = reader.ReadToEnd();
53 log.DebugFormat("JSON response: {0}", body);
54 return new StringReader(body);
59 public static TOut NullSafe<TIn, TOut>(this TIn obj, Func<TIn, TOut> memberAction)
61 //Note we should not use obj != null because it can not test value types and also
62 //compiler has to lift the type to a nullable type for doing the comparision with null.
63 return (!EqualityComparer<TIn>.Default.Equals(obj, default(TIn))) ? memberAction(obj) : default(TOut);
67 public static IEnumerable<T> Range<T>(this IList<T> list, int start, int end)
69 Contract.Requires(start >= 0);
70 Contract.Requires(end < list.Count);
71 Contract.Requires(start <= end);
76 for (var i = 0; i <= end; i++)
83 public static Task<byte[]> UploadDataTaskAsync(this WebClient webClient, Uri address, string method, byte[] data, CancellationToken cancellationToken, IProgress<UploadProgressChangedEventArgs> progress)
85 var tcs = new TaskCompletionSource<byte[]>(address);
86 if (cancellationToken.IsCancellationRequested)
92 CancellationTokenRegistration ctr = cancellationToken.Register(()=>
94 webClient.CancelAsync();
96 UploadDataCompletedEventHandler completedHandler = null;
97 UploadProgressChangedEventHandler progressHandler = null;
99 progressHandler = (s, e) => PithosEAPCommon.HandleProgress(tcs, e, () => e, progress);
100 completedHandler =(sender, e) =>PithosEAPCommon.HandleCompletion(tcs, true, e,() => e.Result,() =>
103 webClient.UploadDataCompleted -= completedHandler;
104 webClient.UploadProgressChanged -= progressHandler;
106 webClient.UploadDataCompleted += completedHandler;
107 webClient.UploadProgressChanged += progressHandler;
110 webClient.UploadDataAsync(address, method, data, tcs);
111 if (cancellationToken.IsCancellationRequested)
112 webClient.CancelAsync();
116 webClient.UploadDataCompleted -= completedHandler;
117 webClient.UploadProgressChanged -= progressHandler;
126 internal static class PithosEAPCommon
128 internal static void HandleProgress<T, E>(TaskCompletionSource<T> tcs, ProgressChangedEventArgs eventArgs, Func<E> getProgress, IProgress<E> callback)
130 if (eventArgs.UserState != tcs)
132 callback.Report(getProgress());
135 internal static void HandleCompletion<T>(TaskCompletionSource<T> tcs, bool requireMatch, AsyncCompletedEventArgs e, Func<T> getResult, Action unregisterHandler)
139 if (e.UserState != tcs)
149 tcs.TrySetCanceled();
150 else if (e.Error != null)
151 tcs.TrySetException(e.Error);
153 tcs.TrySetResult(getResult());