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"]);