public Task <Stream> ReadAsStreamAsync() { CheckDisposed(); TaskCompletionSource <Stream> tcs = new TaskCompletionSource <Stream>(); if (contentReadStream == null && IsBuffered) { // We cast bufferedContent.Length to 'int': The framework doesn't support arrays > int.MaxValue, // so the length will always be in the 'int' range. contentReadStream = new MemoryStream(bufferedContent.GetBuffer(), 0, (int)bufferedContent.Length, false, false); } if (contentReadStream != null) { tcs.TrySetResult(contentReadStream); return(tcs.Task); } CreateContentReadStreamAsync().ContinueWithStandard(task => { if (!HttpUtilities.HandleFaultsAndCancelation(task, tcs)) { contentReadStream = task.Result; tcs.TrySetResult(contentReadStream); } }); return(tcs.Task); }
// Returns true if the task was faulted or canceled and sets tcs accordingly. Non-success status codes count as // faults in cases where the HttpResponseMessage object will not be returned to the developer. private static bool HandleRequestFaultsAndCancelation <T>(Task <HttpResponseMessage> task, TaskCompletionSource <T> tcs) { if (HttpUtilities.HandleFaultsAndCancelation(task, tcs)) { return(true); } HttpResponseMessage response = task.Result; if (!response.IsSuccessStatusCode) { if (response.Content != null) { response.Content.Dispose(); } tcs.TrySetException(new HttpRequestException( string.Format(System.Globalization.CultureInfo.InvariantCulture, SR.net_http_message_not_success_statuscode, (int)response.StatusCode, response.ReasonPhrase))); return(true); } return(false); }
public Task <Stream> ReadAsStreamAsync() { CheckDisposed(); TaskCompletionSource <Stream> tcs = new TaskCompletionSource <Stream>(); if (_contentReadStream == null && IsBuffered) { byte[] data = this.GetDataBuffer(_bufferedContent); // We can cast bufferedContent.Length to 'int' since the length will always be in the 'int' range // The .NET Framework doesn't support array lengths > int.MaxValue. Debug.Assert(_bufferedContent.Length <= (long)int.MaxValue); _contentReadStream = new MemoryStream(data, 0, (int)_bufferedContent.Length, false); } if (_contentReadStream != null) { tcs.TrySetResult(_contentReadStream); return(tcs.Task); } CreateContentReadStreamAsync().ContinueWithStandard(task => { if (!HttpUtilities.HandleFaultsAndCancelation(task, tcs)) { _contentReadStream = task.Result; tcs.TrySetResult(_contentReadStream); } }); return(tcs.Task); }
public Task <byte[]> ReadAsByteArrayAsync() { CheckDisposed(); TaskCompletionSource <byte[]> tcs = new TaskCompletionSource <byte[]>(); LoadIntoBufferAsync().ContinueWithStandard(task => { if (!HttpUtilities.HandleFaultsAndCancelation(task, tcs)) { tcs.TrySetResult(bufferedContent.ToArray()); } }); return(tcs.Task); }
protected virtual Task <Stream> CreateContentReadStreamAsync() { TaskCompletionSource <Stream> tcs = new TaskCompletionSource <Stream>(); // By default just buffer the content to a memory stream. Derived classes can override this behavior // if there is a better way to retrieve the content as stream (e.g. byte array/string use a more efficient // way, like wrapping a read-only MemoryStream around the bytes/string) LoadIntoBufferAsync().ContinueWithStandard(task => { if (!HttpUtilities.HandleFaultsAndCancelation(task, tcs)) { tcs.TrySetResult(bufferedContent); } }); return(tcs.Task); }
private Task <Stream> ReadAsStreamAsyncCore() { TaskCompletionSource <Stream> tcs = new TaskCompletionSource <Stream>(this); CreateContentReadStreamAsync().ContinueWithStandard(tcs, (task, state) => { var innerTcs = (TaskCompletionSource <Stream>)state; var innerThis = (HttpContent)innerTcs.Task.AsyncState; if (!HttpUtilities.HandleFaultsAndCancelation(task, innerTcs)) { innerThis._contentReadStream = task.Result; innerTcs.TrySetResult(innerThis._contentReadStream); } }); return(tcs.Task); }
public Task <byte[]> ReadAsByteArrayAsync() { CheckDisposed(); var tcs = new TaskCompletionSource <byte[]>(this); LoadIntoBufferAsync().ContinueWithStandard(tcs, (task, state) => { var innerTcs = (TaskCompletionSource <byte[]>)state; var innerThis = (HttpContent)innerTcs.Task.AsyncState; if (!HttpUtilities.HandleFaultsAndCancelation(task, innerTcs)) { innerTcs.TrySetResult(innerThis._bufferedContent.ToArray()); } }); return(tcs.Task); }
private Task <T> GetContentAsync <T>(Uri requestUri, HttpCompletionOption completionOption, T defaultValue, Func <HttpContent, Task <T> > readAs) { TaskCompletionSource <T> tcs = new TaskCompletionSource <T>(); GetAsync(requestUri, completionOption).ContinueWithStandard(requestTask => { if (HandleRequestFaultsAndCancelation(requestTask, tcs)) { return; } HttpResponseMessage response = requestTask.Result; if (response.Content == null) { tcs.TrySetResult(defaultValue); return; } try { readAs(response.Content).ContinueWithStandard(contentTask => { if (!HttpUtilities.HandleFaultsAndCancelation(contentTask, tcs)) { tcs.TrySetResult(contentTask.Result); } }); } catch (Exception ex) { tcs.TrySetException(ex); } }); return(tcs.Task); }
public Task <string> ReadAsStringAsync() { CheckDisposed(); var tcs = new TaskCompletionSource <string>(this); LoadIntoBufferAsync().ContinueWithStandard(tcs, (task, state) => { var innerTcs = (TaskCompletionSource <string>)state; var innerThis = (HttpContent)innerTcs.Task.AsyncState; if (HttpUtilities.HandleFaultsAndCancelation(task, innerTcs)) { return; } if (innerThis._bufferedContent.Length == 0) { innerTcs.TrySetResult(string.Empty); return; } // We don't validate the Content-Encoding header: If the content was encoded, it's the caller's // responsibility to make sure to only call ReadAsString() on already decoded content. E.g. if the // Content-Encoding is 'gzip' the user should set HttpClientHandler.AutomaticDecompression to get a // decoded response stream. Encoding encoding = null; int bomLength = -1; byte[] data = innerThis.GetDataBuffer(innerThis._bufferedContent); int dataLength = (int)innerThis._bufferedContent.Length; // Data is the raw buffer, it may not be full. // If we do have encoding information in the 'Content-Type' header, use that information to convert // the content to a string. if ((innerThis.Headers.ContentType != null) && (innerThis.Headers.ContentType.CharSet != null)) { try { encoding = Encoding.GetEncoding(innerThis.Headers.ContentType.CharSet); } catch (ArgumentException e) { innerTcs.TrySetException(new InvalidOperationException(SR.net_http_content_invalid_charset, e)); return; } } // If no content encoding is listed in the ContentType HTTP header, or no Content-Type header present, // then check for a byte-order-mark (BOM) in the data to figure out the encoding. if (encoding == null) { byte[] preamble; foreach (Encoding testEncoding in s_encodingsWithBom) { preamble = testEncoding.GetPreamble(); if (ByteArrayHasPrefix(data, dataLength, preamble)) { encoding = testEncoding; bomLength = preamble.Length; break; } } } // Use the default encoding if we couldn't detect one. encoding = encoding ?? DefaultStringEncoding; // BOM characters may be present even if a charset was specified. if (bomLength == -1) { byte[] preamble = encoding.GetPreamble(); if (ByteArrayHasPrefix(data, dataLength, preamble)) { bomLength = preamble.Length; } else { bomLength = 0; } } try { // Drop the BOM when decoding the data. string result = encoding.GetString(data, bomLength, dataLength - bomLength); innerTcs.TrySetResult(result); } catch (Exception ex) { innerTcs.TrySetException(ex); } }); return(tcs.Task); }