From ff31b958fe0219b5252fc026ffbbd3938b630ff9 Mon Sep 17 00:00:00 2001 From: Chris Ross Date: Tue, 24 Jun 2014 12:06:55 -0700 Subject: [PATCH] #80 - Add CancellationToken to GetClientCertAsyc, GetFormAsync. --- src/Microsoft.AspNet.Http/HttpRequest.cs | 13 +++++++++++-- .../IHttpClientCertificateFeature.cs | 3 ++- src/Microsoft.AspNet.Owin/OwinEnvironment.cs | 3 ++- .../OwinFeatureCollection.cs | 2 +- .../DefaultHttpRequest.cs | 4 ++-- src/Microsoft.AspNet.PipelineCore/FormFeature.cs | 15 ++++++++++++--- src/Microsoft.AspNet.PipelineCore/IFormFeature.cs | 3 ++- .../FormFeatureTests.cs | 9 +++++---- 8 files changed, 37 insertions(+), 15 deletions(-) diff --git a/src/Microsoft.AspNet.Http/HttpRequest.cs b/src/Microsoft.AspNet.Http/HttpRequest.cs index 9a09b01a65..44fa1e945b 100644 --- a/src/Microsoft.AspNet.Http/HttpRequest.cs +++ b/src/Microsoft.AspNet.Http/HttpRequest.cs @@ -63,10 +63,19 @@ namespace Microsoft.AspNet.Http public abstract IReadableStringCollection Query { get; } /// - /// Gets the query value collection form collection. + /// Gets the form collection. /// /// The form collection parsed from the request body. - public abstract Task GetFormAsync(); + public virtual Task GetFormAsync() + { + return GetFormAsync(CancellationToken.None); + } + + /// + /// Gets the form collection. + /// + /// The form collection parsed from the request body. + public abstract Task GetFormAsync(CancellationToken cancel); /// /// Gets or set the owin.RequestProtocol. diff --git a/src/Microsoft.AspNet.HttpFeature/IHttpClientCertificateFeature.cs b/src/Microsoft.AspNet.HttpFeature/IHttpClientCertificateFeature.cs index ccaf9b1298..2c9e77bdb1 100644 --- a/src/Microsoft.AspNet.HttpFeature/IHttpClientCertificateFeature.cs +++ b/src/Microsoft.AspNet.HttpFeature/IHttpClientCertificateFeature.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Security.Cryptography.X509Certificates; +using System.Threading; using System.Threading.Tasks; using Microsoft.Framework.Runtime; @@ -19,6 +20,6 @@ namespace Microsoft.AspNet.HttpFeature /// Asynchronously retrieves the client certificate, if any. /// /// - Task GetClientCertificateAsync(); + Task GetClientCertificateAsync(CancellationToken cancel); } } diff --git a/src/Microsoft.AspNet.Owin/OwinEnvironment.cs b/src/Microsoft.AspNet.Owin/OwinEnvironment.cs index 82656dcba9..8f6f9c4951 100644 --- a/src/Microsoft.AspNet.Owin/OwinEnvironment.cs +++ b/src/Microsoft.AspNet.Owin/OwinEnvironment.cs @@ -69,7 +69,8 @@ namespace Microsoft.AspNet.Owin { _entries.Add(OwinConstants.CommonKeys.ClientCertificate, new FeatureMap(feature => feature.ClientCertificate, (feature, value) => feature.ClientCertificate = (X509Certificate)value)); - _entries.Add(OwinConstants.CommonKeys.LoadClientCertAsync, new FeatureMap(feature => new Func(feature.GetClientCertificateAsync))); + _entries.Add(OwinConstants.CommonKeys.LoadClientCertAsync, new FeatureMap( + feature => new Func(() => feature.GetClientCertificateAsync(CancellationToken.None)))); } _context.Items[typeof(HttpContext).FullName] = _context; // Store for lookup when we transition back out of OWIN diff --git a/src/Microsoft.AspNet.Owin/OwinFeatureCollection.cs b/src/Microsoft.AspNet.Owin/OwinFeatureCollection.cs index 0e0a5abeb9..8994dfa6f4 100644 --- a/src/Microsoft.AspNet.Owin/OwinFeatureCollection.cs +++ b/src/Microsoft.AspNet.Owin/OwinFeatureCollection.cs @@ -203,7 +203,7 @@ namespace Microsoft.AspNet.Owin set { Prop(OwinConstants.CommonKeys.ClientCertificate, value); } } - Task IHttpClientCertificateFeature.GetClientCertificateAsync() + Task IHttpClientCertificateFeature.GetClientCertificateAsync(CancellationToken cancel) { throw new NotImplementedException(); } diff --git a/src/Microsoft.AspNet.PipelineCore/DefaultHttpRequest.cs b/src/Microsoft.AspNet.PipelineCore/DefaultHttpRequest.cs index 29a1e34b4c..eba4253862 100644 --- a/src/Microsoft.AspNet.PipelineCore/DefaultHttpRequest.cs +++ b/src/Microsoft.AspNet.PipelineCore/DefaultHttpRequest.cs @@ -129,9 +129,9 @@ namespace Microsoft.AspNet.PipelineCore get { return QueryFeature.Query; } } - public override Task GetFormAsync() + public override Task GetFormAsync(CancellationToken cancel) { - return FormFeature.GetFormAsync(); + return FormFeature.GetFormAsync(cancel); } public override string Protocol diff --git a/src/Microsoft.AspNet.PipelineCore/FormFeature.cs b/src/Microsoft.AspNet.PipelineCore/FormFeature.cs index ad7598af3e..86e1d4c0f3 100644 --- a/src/Microsoft.AspNet.PipelineCore/FormFeature.cs +++ b/src/Microsoft.AspNet.PipelineCore/FormFeature.cs @@ -3,9 +3,10 @@ using System.IO; using System.Text; +using System.Threading; using System.Threading.Tasks; -using Microsoft.AspNet.Http; using Microsoft.AspNet.FeatureModel; +using Microsoft.AspNet.Http; using Microsoft.AspNet.HttpFeature; using Microsoft.AspNet.PipelineCore.Collections; using Microsoft.AspNet.PipelineCore.Infrastructure; @@ -24,14 +25,22 @@ namespace Microsoft.AspNet.PipelineCore _features = features; } - public async Task GetFormAsync() + public async Task GetFormAsync(CancellationToken cancel) { var body = _request.Fetch(_features).Body; if (_bodyStream == null || _bodyStream != body) { _bodyStream = body; - using (var streamReader = new StreamReader(body, Encoding.UTF8, + if (!_bodyStream.CanSeek) + { + MemoryStream buffer = new MemoryStream(); + await _bodyStream.CopyToAsync(buffer, 4096, cancel); + _bodyStream = buffer; + _request.Fetch(_features).Body = _bodyStream; + _bodyStream.Seek(0, SeekOrigin.Begin); + } + using (var streamReader = new StreamReader(_bodyStream, Encoding.UTF8, detectEncodingFromByteOrderMarks: true, bufferSize: 1024, leaveOpen: true)) { diff --git a/src/Microsoft.AspNet.PipelineCore/IFormFeature.cs b/src/Microsoft.AspNet.PipelineCore/IFormFeature.cs index 261b77d551..0aed1a00f3 100644 --- a/src/Microsoft.AspNet.PipelineCore/IFormFeature.cs +++ b/src/Microsoft.AspNet.PipelineCore/IFormFeature.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Threading; using System.Threading.Tasks; using Microsoft.AspNet.Http; @@ -8,6 +9,6 @@ namespace Microsoft.AspNet.PipelineCore { public interface IFormFeature { - Task GetFormAsync(); + Task GetFormAsync(CancellationToken cancel); } } diff --git a/test/Microsoft.AspNet.PipelineCore.Tests/FormFeatureTests.cs b/test/Microsoft.AspNet.PipelineCore.Tests/FormFeatureTests.cs index 6566bc75eb..b7fdc8f563 100644 --- a/test/Microsoft.AspNet.PipelineCore.Tests/FormFeatureTests.cs +++ b/test/Microsoft.AspNet.PipelineCore.Tests/FormFeatureTests.cs @@ -3,6 +3,7 @@ using System.IO; using System.Text; +using System.Threading; using System.Threading.Tasks; using Microsoft.AspNet.FeatureModel; using Microsoft.AspNet.HttpFeature; @@ -29,7 +30,7 @@ namespace Microsoft.AspNet.PipelineCore.Tests var provider = new FormFeature(features.Object); // Act - var formCollection = await provider.GetFormAsync(); + var formCollection = await provider.GetFormAsync(CancellationToken.None); // Assert Assert.Equal("bar", formCollection["foo"]); @@ -53,16 +54,16 @@ namespace Microsoft.AspNet.PipelineCore.Tests var provider = new FormFeature(features.Object); // Act - 1 - var formCollection = await provider.GetFormAsync(); + var formCollection = await provider.GetFormAsync(CancellationToken.None); // Assert - 1 Assert.Equal("bar", formCollection["foo"]); Assert.Equal("2", formCollection["baz"]); - Assert.Same(formCollection, await provider.GetFormAsync()); + Assert.Same(formCollection, await provider.GetFormAsync(CancellationToken.None)); // Act - 2 request.SetupGet(r => r.Body).Returns(new MemoryStream(formContent2)); - formCollection = await provider.GetFormAsync(); + formCollection = await provider.GetFormAsync(CancellationToken.None); // Assert - 2 Assert.Equal("value", formCollection["collection2"]);