//
using System.Net.Http.Headers;
+using System.IO;
+using System.Threading.Tasks;
+using System.Text;
namespace System.Net.Http
{
public abstract class HttpContent : IDisposable
{
+ sealed class FixedMemoryStream : MemoryStream
+ {
+ readonly long maxSize;
+
+ public FixedMemoryStream (long maxSize)
+ : base ()
+ {
+ this.maxSize = maxSize;
+ }
+
+ void CheckOverflow (int count)
+ {
+ if (Length + count > maxSize)
+ throw new HttpRequestException (string.Format ("Cannot write more bytes to the buffer than the configured maximum buffer size: {0}", maxSize));
+ }
+
+ public override void WriteByte (byte value)
+ {
+ CheckOverflow (1);
+ base.WriteByte (value);
+ }
+
+ public override void Write (byte[] buffer, int offset, int count)
+ {
+ CheckOverflow (count);
+ base.Write (buffer, offset, count);
+ }
+ }
+
+ FixedMemoryStream buffer;
+ Stream stream;
+ bool disposed;
+ HttpContentHeaders headers;
+
public HttpContentHeaders Headers {
get {
- return new HttpContentHeaders ();
+ return headers ?? (headers = new HttpContentHeaders (this));
}
}
+
+ public Task CopyToAsync (Stream stream)
+ {
+ return CopyToAsync (stream, null);
+ }
+
+ public Task CopyToAsync (Stream stream, TransportContext context)
+ {
+ if (stream == null)
+ throw new ArgumentNullException ("stream");
+
+ return SerializeToStreamAsync (stream, context);
+ }
+
+ protected async virtual Task<Stream> CreateContentReadStreamAsync ()
+ {
+ await LoadIntoBufferAsync ().ConfigureAwait (false);
+ return buffer;
+ }
+ static FixedMemoryStream CreateFixedMemoryStream (long maxBufferSize)
+ {
+ return new FixedMemoryStream (maxBufferSize);
+ }
+
public void Dispose ()
{
Dispose (true);
protected virtual void Dispose (bool disposing)
{
+ if (disposing && !disposed) {
+ disposed = true;
+
+ if (buffer != null)
+ buffer.Dispose ();
+ }
+ }
+
+ public Task LoadIntoBufferAsync ()
+ {
+ return LoadIntoBufferAsync (65536);
}
- public string ReadAsString ()
+ public async Task LoadIntoBufferAsync (long maxBufferSize)
{
- return null;
+ if (disposed)
+ throw new ObjectDisposedException (GetType ().ToString ());
+
+ if (buffer != null)
+ return;
+
+ buffer = CreateFixedMemoryStream (maxBufferSize);
+ await SerializeToStreamAsync (buffer, null).ConfigureAwait (false);
+ buffer.Seek (0, SeekOrigin.Begin);
+ }
+
+ public async Task<Stream> ReadAsStreamAsync ()
+ {
+ if (disposed)
+ throw new ObjectDisposedException (GetType ().ToString ());
+
+ if (stream == null)
+ stream = await CreateContentReadStreamAsync ().ConfigureAwait (false);
+
+ return stream;
}
+
+ public async Task<byte[]> ReadAsByteArrayAsync ()
+ {
+ await LoadIntoBufferAsync ().ConfigureAwait (false);
+ return buffer.ToArray ();
+ }
+
+ public async Task<string> ReadAsStringAsync ()
+ {
+ await LoadIntoBufferAsync ().ConfigureAwait (false);
+ if (buffer.Length == 0)
+ return string.Empty;
+
+ Encoding encoding;
+ if (headers != null && headers.ContentType != null && headers.ContentType.CharSet != null) {
+ encoding = Encoding.GetEncoding (headers.ContentType.CharSet);
+ } else {
+ encoding = Encoding.UTF8;
+ }
+
+ return encoding.GetString (buffer.GetBuffer (), 0, (int) buffer.Length);
+ }
+
+ protected internal abstract Task SerializeToStreamAsync (Stream stream, TransportContext context);
+ protected internal abstract bool TryComputeLength (out long length);
}
}