aspnetcore/src/Microsoft.AspNet.Owin/OwinFeatureCollection.cs

372 lines
11 KiB
C#

// 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;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNet.HttpFeature;
using Microsoft.AspNet.FeatureModel;
namespace Microsoft.AspNet.Owin
{
using SendFileFunc = Func<string, long, long?, CancellationToken, Task>;
public class OwinFeatureCollection :
IFeatureCollection,
IHttpRequestFeature,
IHttpResponseFeature,
IHttpConnectionFeature,
IHttpSendFileFeature,
IHttpClientCertificateFeature,
IOwinEnvironmentFeature
{
public IDictionary<string, object> Environment { get; set; }
public OwinFeatureCollection(IDictionary<string, object> environment)
{
Environment = environment;
}
T Prop<T>(string key)
{
object value;
if (Environment.TryGetValue(key, out value) && value is T)
{
return (T)value;
}
return default(T);
}
void Prop(string key, object value)
{
Environment[key] = value;
}
string IHttpRequestFeature.Protocol
{
get { return Prop<string>(OwinConstants.RequestProtocol); }
set { Prop(OwinConstants.RequestProtocol, value); }
}
string IHttpRequestFeature.Scheme
{
get { return Prop<string>(OwinConstants.RequestScheme); }
set { Prop(OwinConstants.RequestScheme, value); }
}
string IHttpRequestFeature.Method
{
get { return Prop<string>(OwinConstants.RequestMethod); }
set { Prop(OwinConstants.RequestMethod, value); }
}
string IHttpRequestFeature.PathBase
{
get { return Prop<string>(OwinConstants.RequestPathBase); }
set { Prop(OwinConstants.RequestPathBase, value); }
}
string IHttpRequestFeature.Path
{
get { return Prop<string>(OwinConstants.RequestPath); }
set { Prop(OwinConstants.RequestPath, value); }
}
string IHttpRequestFeature.QueryString
{
get { return Prop<string>(OwinConstants.RequestQueryString); }
set { Prop(OwinConstants.RequestQueryString, value); }
}
IDictionary<string, string[]> IHttpRequestFeature.Headers
{
get { return Prop<IDictionary<string, string[]>>(OwinConstants.RequestHeaders); }
set { Prop(OwinConstants.RequestHeaders, value); }
}
Stream IHttpRequestFeature.Body
{
get { return Prop<Stream>(OwinConstants.RequestBody); }
set { Prop(OwinConstants.RequestBody, value); }
}
int IHttpResponseFeature.StatusCode
{
get { return Prop<int>(OwinConstants.ResponseStatusCode); }
set { Prop(OwinConstants.ResponseStatusCode, value); }
}
string IHttpResponseFeature.ReasonPhrase
{
get { return Prop<string>(OwinConstants.ResponseReasonPhrase); }
set { Prop(OwinConstants.ResponseReasonPhrase, value); }
}
IDictionary<string, string[]> IHttpResponseFeature.Headers
{
get { return Prop<IDictionary<string, string[]>>(OwinConstants.ResponseHeaders); }
set { Prop(OwinConstants.ResponseHeaders, value); }
}
Stream IHttpResponseFeature.Body
{
get { return Prop<Stream>(OwinConstants.ResponseBody); }
set { Prop(OwinConstants.ResponseBody, value); }
}
void IHttpResponseFeature.OnSendingHeaders(Action<object> callback, object state)
{
var register = Prop<Action<Action<object>, object>>(OwinConstants.CommonKeys.OnSendingHeaders);
if (register == null)
{
throw new NotSupportedException(OwinConstants.CommonKeys.OnSendingHeaders);
}
register(callback, state);
}
IPAddress IHttpConnectionFeature.RemoteIpAddress
{
get { return IPAddress.Parse(Prop<string>(OwinConstants.CommonKeys.RemoteIpAddress)); }
set { Prop(OwinConstants.CommonKeys.RemoteIpAddress, value.ToString()); }
}
IPAddress IHttpConnectionFeature.LocalIpAddress
{
get { return IPAddress.Parse(Prop<string>(OwinConstants.CommonKeys.LocalIpAddress)); }
set { Prop(OwinConstants.CommonKeys.LocalIpAddress, value.ToString()); }
}
int IHttpConnectionFeature.RemotePort
{
get { return int.Parse(Prop<string>(OwinConstants.CommonKeys.RemotePort)); }
set { Prop(OwinConstants.CommonKeys.RemotePort, value.ToString(CultureInfo.InvariantCulture)); }
}
int IHttpConnectionFeature.LocalPort
{
get { return int.Parse(Prop<string>(OwinConstants.CommonKeys.LocalPort)); }
set { Prop(OwinConstants.CommonKeys.LocalPort, value.ToString(CultureInfo.InvariantCulture)); }
}
bool IHttpConnectionFeature.IsLocal
{
get { return Prop<bool>(OwinConstants.CommonKeys.IsLocal); }
set { Prop(OwinConstants.CommonKeys.LocalPort, value); }
}
private bool SupportsSendFile
{
get
{
object obj;
return Environment.TryGetValue(OwinConstants.SendFiles.SendAsync, out obj) && obj != null;
}
}
Task IHttpSendFileFeature.SendFileAsync(string path, long offset, long? length, CancellationToken cancellation)
{
object obj;
if (Environment.TryGetValue(OwinConstants.SendFiles.SendAsync, out obj))
{
var 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", ((IHttpRequestFeature)this).Scheme, StringComparison.OrdinalIgnoreCase)
&& (Environment.TryGetValue(OwinConstants.CommonKeys.LoadClientCertAsync, out obj)
|| Environment.TryGetValue(OwinConstants.CommonKeys.ClientCertificate, out obj))
&& obj != null)
{
return true;
}
return false;
}
}
X509Certificate IHttpClientCertificateFeature.ClientCertificate
{
get { return Prop<X509Certificate>(OwinConstants.CommonKeys.ClientCertificate); }
set { Prop(OwinConstants.CommonKeys.ClientCertificate, value); }
}
Task<X509Certificate> IHttpClientCertificateFeature.GetClientCertificateAsync()
{
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(IHttpSendFileFeature))
{
return SupportsSendFile;
}
else if (key == typeof(IHttpClientCertificateFeature))
{
return SupportsClientCerts;
}
// The rest of the features are always supported.
return true;
}
return false;
}
public ICollection<Type> Keys
{
get
{
var keys = new List<Type>()
{
typeof(IHttpRequestFeature),
typeof(IHttpResponseFeature),
typeof(IHttpConnectionFeature),
typeof(IOwinEnvironmentFeature),
};
if (SupportsSendFile)
{
keys.Add(typeof(IHttpSendFileFeature));
}
if (SupportsClientCerts)
{
keys.Add(typeof(IHttpClientCertificateFeature));
}
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<object> 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<Type, object> item)
{
throw new NotSupportedException();
}
public void Clear()
{
throw new NotSupportedException();
}
public bool Contains(KeyValuePair<Type, object> item)
{
object result;
return TryGetValue(item.Key, out result) && result.Equals(item.Value);
}
public void CopyTo(KeyValuePair<Type, object>[] array, int arrayIndex)
{
if (array == null)
{
throw new ArgumentNullException("array");
}
if (arrayIndex < 0 || arrayIndex > array.Length)
{
throw new ArgumentOutOfRangeException("arrayIndex", arrayIndex, string.Empty);
}
var keys = Keys;
if (keys.Count > array.Length - arrayIndex)
{
throw new ArgumentException();
}
foreach (var key in keys)
{
array[arrayIndex++] = new KeyValuePair<Type, object>(key, this[key]);
}
}
public int Count
{
get { return Keys.Count; }
}
public bool IsReadOnly
{
get { return true; }
}
public bool Remove(KeyValuePair<Type, object> item)
{
throw new NotSupportedException();
}
public IEnumerator<KeyValuePair<Type, object>> GetEnumerator()
{
return Keys.Select(type => new KeyValuePair<Type, object>(type, this[type])).GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Dispose()
{
}
}
}