diff --git a/src/Microsoft.AspNet.AppBuilderSupport/AppBuilderSupportExtensions.cs b/src/Microsoft.AspNet.AppBuilderSupport/AppBuilderSupportExtensions.cs index dfb66eb492..215afb8bcf 100644 --- a/src/Microsoft.AspNet.AppBuilderSupport/AppBuilderSupportExtensions.cs +++ b/src/Microsoft.AspNet.AppBuilderSupport/AppBuilderSupportExtensions.cs @@ -31,8 +31,7 @@ namespace Owin return app.Invoke( new DefaultHttpContext( new FeatureCollection( - new FeatureObject( - new OwinHttpEnvironment(env))))); + new OwinHttpEnvironment(env)))); }; }; return appBuilder.Use(middleware1); diff --git a/src/Microsoft.AspNet.AppBuilderSupport/OwinConstants.cs b/src/Microsoft.AspNet.AppBuilderSupport/OwinConstants.cs index c7eafe6019..45aabf2913 100644 --- a/src/Microsoft.AspNet.AppBuilderSupport/OwinConstants.cs +++ b/src/Microsoft.AspNet.AppBuilderSupport/OwinConstants.cs @@ -56,6 +56,7 @@ internal static class CommonKeys { public const string ClientCertificate = "ssl.ClientCertificate"; + public const string LoadClientCertAsync = "ssl.LoadClientCertAsync"; public const string RemoteIpAddress = "server.RemoteIpAddress"; public const string RemotePort = "server.RemotePort"; public const string LocalIpAddress = "server.LocalIpAddress"; diff --git a/src/Microsoft.AspNet.AppBuilderSupport/OwinHttpEnvironment.cs b/src/Microsoft.AspNet.AppBuilderSupport/OwinHttpEnvironment.cs index 0fb7a5ea01..b03c9bd7fe 100644 --- a/src/Microsoft.AspNet.AppBuilderSupport/OwinHttpEnvironment.cs +++ b/src/Microsoft.AspNet.AppBuilderSupport/OwinHttpEnvironment.cs @@ -2,17 +2,23 @@ using System; using System.Collections.Generic; using System.Globalization; using System.IO; +using System.Linq; using System.Net; +using System.Reflection; #if NET45 using System.Security.Cryptography.X509Certificates; #endif using System.Threading; using System.Threading.Tasks; using Microsoft.AspNet.HttpFeature; +using Microsoft.AspNet.FeatureModel; namespace Microsoft.AspNet.PipelineCore.Owin { + using SendFileFunc = Func; + public class OwinHttpEnvironment : + IFeatureCollection, IHttpRequestInformation, IHttpResponseInformation, IHttpConnection, @@ -149,9 +155,40 @@ namespace Microsoft.AspNet.PipelineCore.Owin set { Prop(OwinConstants.CommonKeys.LocalPort, value); } } + private bool SupportsSendFile + { + get + { + object obj; + return Environment.TryGetValue(OwinConstants.SendFiles.SendAsync, out obj) && obj != null; + } + } + Task IHttpSendFile.SendFileAsync(string path, long offset, long? length, CancellationToken cancellation) { - throw new NotImplementedException(); + object obj; + if (Environment.TryGetValue(OwinConstants.SendFiles.SendAsync, out obj)) + { + SendFileFunc func = (SendFileFunc)obj; + return func(path, offset, length, cancellation); + } + throw new NotSupportedException(OwinConstants.SendFiles.SendAsync); + } + + private bool SupportsClientCerts + { + get + { + object obj; + if (string.Equals("https", ((IHttpRequestInformation)this).Scheme, StringComparison.OrdinalIgnoreCase) + && (Environment.TryGetValue(OwinConstants.CommonKeys.LoadClientCertAsync, out obj) + || Environment.TryGetValue(OwinConstants.CommonKeys.ClientCertificate, out obj)) + && obj != null) + { + return true; + } + return false; + } } #if NET45 X509Certificate IHttpTransportLayerSecurity.ClientCertificate @@ -164,5 +201,146 @@ namespace Microsoft.AspNet.PipelineCore.Owin { throw new NotImplementedException(); } + + public int Revision + { + get { return 0; } // Not modifiable + } + + public void Add(Type key, object value) + { + throw new NotSupportedException(); + } + + public bool ContainsKey(Type key) + { + // Does this type implement the requested interface? + if (key.GetTypeInfo().IsAssignableFrom(this.GetType().GetTypeInfo())) + { + // Check for conditional features + if (key == typeof(IHttpSendFile)) + { + return SupportsSendFile; + } + else if (key == typeof(IHttpTransportLayerSecurity)) + { + return SupportsClientCerts; + } + + // The rest of the features are always supported. + return true; + } + return false; + } + + public ICollection Keys + { + get + { + IList keys = new List() + { + typeof(IHttpRequestInformation), + typeof(IHttpResponseInformation), + typeof(IHttpConnection), + typeof(ICanHasOwinEnvironment), + }; + if (SupportsSendFile) + { + keys.Add(typeof(IHttpSendFile)); + } + if (SupportsClientCerts) + { + keys.Add(typeof(IHttpTransportLayerSecurity)); + } + return keys; + } + } + + public bool Remove(Type key) + { + throw new NotSupportedException(); + } + + public bool TryGetValue(Type key, out object value) + { + if (ContainsKey(key)) + { + value = this; + return true; + } + value = null; + return false; + } + + public ICollection Values + { + get { throw new NotSupportedException(); } + } + + public object this[Type key] + { + get + { + object value; + if (TryGetValue(key, out value)) + { + return value; + } + throw new KeyNotFoundException(key.FullName); + } + set + { + throw new NotSupportedException(); + } + } + + public void Add(KeyValuePair item) + { + throw new NotSupportedException(); + } + + public void Clear() + { + throw new NotSupportedException(); + } + + public bool Contains(KeyValuePair item) + { + throw new NotImplementedException(); + } + + public void CopyTo(KeyValuePair[] array, int arrayIndex) + { + throw new NotImplementedException(); + } + + public int Count + { + get { return Keys.Count; } + } + + public bool IsReadOnly + { + get { return true; } + } + + public bool Remove(KeyValuePair item) + { + throw new NotSupportedException(); + } + + public IEnumerator> GetEnumerator() + { + return Keys.Select(type => new KeyValuePair(type, this[type])).GetEnumerator(); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public void Dispose() + { + } } } \ No newline at end of file