| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 |
- // <copyright>
- // Copyright (c) Microsoft Corporation. All rights reserved.
- // </copyright>
- namespace System.ServiceModel.Channels
- {
- using System;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.Configuration;
- using System.Globalization;
- using System.Net.Http;
- using System.Reflection;
- using System.Runtime;
- using System.Runtime.CompilerServices;
- using System.Security;
- using System.Security.Permissions;
- using System.ServiceModel.Configuration;
- /// <summary>
- /// Default HTTP message handler factory used by <see cref="HttpChannelListener"/> upon creation of an <see cref="HttpMessageHandler"/>
- /// for instantiating a set of HTTP message handler types using their default constructors.
- /// For more complex initialization scenarios, derive from <see cref="HttpMessageHandlerFactory"/>
- /// and override the <see cref="HttpMessageHandlerFactory.OnCreate"/> method.
- /// </summary>
- public class HttpMessageHandlerFactory
- {
- static readonly Type delegatingHandlerType = typeof(DelegatingHandler);
- Type[] httpMessageHandlers;
- ConstructorInfo[] handlerCtors;
- Func<IEnumerable<DelegatingHandler>> handlerFunc;
- /// <summary>
- /// Initializes a new instance of the <see cref="HttpMessageHandlerFactory"/> class given
- /// a set of HTTP message handler types to instantiate using their default constructors.
- /// </summary>
- /// <param name="handlers">An ordered list of HTTP message handler types to be invoked as part of an
- /// <see cref="HttpMessageHandler"/> instance.
- /// HTTP message handler types must derive from <see cref="DelegatingHandler"/> and have a public constructor
- /// taking exactly one argument of type <see cref="HttpMessageHandler"/>. The handlers are invoked in a
- /// bottom-up fashion in the incoming path and top-down in the outgoing path. That is, the last entry is called first
- /// for an incoming request messasge but invoked last for an outgoing response message.</param>
- [PermissionSet(SecurityAction.Demand, Unrestricted = true), SecuritySafeCritical]
- [MethodImpl(MethodImplOptions.NoInlining)]
- public HttpMessageHandlerFactory(params Type[] handlers)
- {
- if (handlers == null)
- {
- throw FxTrace.Exception.ArgumentNull("handlers");
- }
- if (handlers.Length == 0)
- {
- throw FxTrace.Exception.Argument("handlers", SR.GetString(SR.InputTypeListEmptyError));
- }
- this.handlerCtors = new ConstructorInfo[handlers.Length];
- for (int cnt = 0; cnt < handlers.Length; cnt++)
- {
- Type handler = handlers[cnt];
- if (handler == null)
- {
- throw FxTrace.Exception.Argument(
- string.Format(CultureInfo.InvariantCulture, "handlers[<<{0}>>]", cnt),
- SR.GetString(SR.HttpMessageHandlerTypeNotSupported, "null", delegatingHandlerType.Name));
- }
- if (!delegatingHandlerType.IsAssignableFrom(handler) || handler.IsAbstract)
- {
- throw FxTrace.Exception.Argument(
- string.Format(CultureInfo.InvariantCulture, "handlers[<<{0}>>]", cnt),
- SR.GetString(SR.HttpMessageHandlerTypeNotSupported, handler.Name, delegatingHandlerType.Name));
- }
- ConstructorInfo ctorInfo = handler.GetConstructor(Type.EmptyTypes);
- if (ctorInfo == null)
- {
- throw FxTrace.Exception.Argument(
- string.Format(CultureInfo.InvariantCulture, "handlers[<<{0}>>]", cnt),
- SR.GetString(SR.HttpMessageHandlerTypeNotSupported, handler.Name, delegatingHandlerType.Name));
- }
- this.handlerCtors[cnt] = ctorInfo;
- }
- this.httpMessageHandlers = handlers;
- }
- /// <summary>
- /// Initializes a new instance of the <see cref="HttpMessageHandlerFactory"/> class given
- /// a function to create a set of <see cref="DelegatingHandler"/> instances.
- /// </summary>
- /// <param name="handlers">A function to generate an ordered list of <see cref="DelegatingHandler"/> instances
- /// to be invoked as part of an <see cref="HttpMessageHandler"/> instance.
- /// The handlers are invoked in a bottom-up fashion in the incoming path and top-down in the outgoing path. That is,
- /// the last entry is called first for an incoming request messasge but invoked last for an outgoing response message.</param>
- [PermissionSet(SecurityAction.Demand, Unrestricted = true), SecuritySafeCritical]
- [MethodImpl(MethodImplOptions.NoInlining)]
- public HttpMessageHandlerFactory(Func<IEnumerable<DelegatingHandler>> handlers)
- {
- if (handlers == null)
- {
- throw FxTrace.Exception.ArgumentNull("handlers");
- }
- this.handlerFunc = handlers;
- }
- /// <summary>
- /// Initializes a new instance of the <see cref="HttpMessageHandlerFactory"/> class.
- /// </summary>
- [PermissionSet(SecurityAction.Demand, Unrestricted = true), SecuritySafeCritical]
- [MethodImpl(MethodImplOptions.NoInlining)]
- protected HttpMessageHandlerFactory()
- {
- }
- /// <summary>
- /// Creates an instance of an <see cref="HttpMessageHandler"/> using the HTTP message handlers
- /// provided in the constructor.
- /// </summary>
- /// <param name="innerChannel">The inner channel represents the destination of the HTTP message channel.</param>
- /// <returns>The HTTP message channel.</returns>
- [PermissionSet(SecurityAction.Demand, Unrestricted = true), SecuritySafeCritical]
- [MethodImpl(MethodImplOptions.NoInlining)]
- public HttpMessageHandler Create(HttpMessageHandler innerChannel)
- {
- if (innerChannel == null)
- {
- throw FxTrace.Exception.ArgumentNull("innerChannel");
- }
- return this.OnCreate(innerChannel);
- }
- internal static HttpMessageHandlerFactory CreateFromConfigurationElement(HttpMessageHandlerFactoryElement configElement)
- {
- Fx.Assert(configElement != null, "configElement should not be null.");
- if (!string.IsNullOrWhiteSpace(configElement.Type))
- {
- if (configElement.Handlers != null && configElement.Handlers.Count > 0)
- {
- throw FxTrace.Exception.AsError(new ConfigurationErrorsException(SR.GetString(SR.HttpMessageHandlerFactoryConfigInvalid_WithBothTypeAndHandlerList, ConfigurationStrings.MessageHandlerFactory, ConfigurationStrings.Type, ConfigurationStrings.Handlers)));
- }
- Type factoryType = HttpChannelUtilities.GetTypeFromAssembliesInCurrentDomain(configElement.Type);
- if (factoryType == null)
- {
- throw FxTrace.Exception.AsError(new ConfigurationErrorsException(SR.GetString(SR.CanNotLoadTypeGotFromConfig, configElement.Type)));
- }
- if (!typeof(HttpMessageHandlerFactory).IsAssignableFrom(factoryType) || factoryType.IsAbstract)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ConfigurationErrorsException(
- SR.GetString(
- SR.WebSocketElementConfigInvalidHttpMessageHandlerFactoryType,
- typeof(HttpMessageHandlerFactory).Name,
- factoryType,
- typeof(HttpMessageHandlerFactory).AssemblyQualifiedName)));
- }
- return Activator.CreateInstance(factoryType) as HttpMessageHandlerFactory;
- }
- else
- {
- if (configElement.Handlers == null || configElement.Handlers.Count == 0)
- {
- return null;
- }
- Type[] handlerList = new Type[configElement.Handlers.Count];
- for (int i = 0; i < configElement.Handlers.Count; i++)
- {
- Type handlerType = HttpChannelUtilities.GetTypeFromAssembliesInCurrentDomain(configElement.Handlers[i].Type);
- if (handlerType == null)
- {
- throw FxTrace.Exception.AsError(new ConfigurationErrorsException(SR.GetString(SR.CanNotLoadTypeGotFromConfig, configElement.Handlers[i].Type)));
- }
- handlerList[i] = handlerType;
- }
- try
- {
- return new HttpMessageHandlerFactory(handlerList);
- }
- catch (ArgumentException ex)
- {
- throw FxTrace.Exception.AsError(new ConfigurationErrorsException(ex.Message, ex));
- }
- }
- }
- internal HttpMessageHandlerFactoryElement GenerateConfigurationElement()
- {
- if (this.handlerFunc != null)
- {
- throw FxTrace.Exception.AsError(new InvalidOperationException(SR.GetString(SR.HttpMessageHandlerFactoryWithFuncCannotGenerateConfig, typeof(HttpMessageHandlerFactory).Name, typeof(Func<IEnumerable<DelegatingHandler>>).Name)));
- }
- Type thisType = this.GetType();
- if (thisType != typeof(HttpMessageHandlerFactory))
- {
- return new HttpMessageHandlerFactoryElement
- {
- Type = thisType.AssemblyQualifiedName
- };
- }
- else
- {
- if (this.httpMessageHandlers != null)
- {
- DelegatingHandlerElementCollection handlerCollection = new DelegatingHandlerElementCollection();
- for (int i = 0; i < this.httpMessageHandlers.Length; i++)
- {
- handlerCollection.Add(new DelegatingHandlerElement(this.httpMessageHandlers[i]));
- }
- return new HttpMessageHandlerFactoryElement
- {
- Handlers = handlerCollection
- };
- }
- }
- return null;
- }
- /// <summary>
- /// Creates an instance of an <see cref="HttpMessageHandler"/> using the HTTP message handlers
- /// provided in the constructor.
- /// </summary>
- /// <param name="innerChannel">The inner channel represents the destination of the HTTP message channel.</param>
- /// <returns>The HTTP message channel.</returns>
- protected virtual HttpMessageHandler OnCreate(HttpMessageHandler innerChannel)
- {
- if (innerChannel == null)
- {
- throw FxTrace.Exception.ArgumentNull("innerChannel");
- }
- // Get handlers either by constructing types or by calling Func
- IEnumerable<DelegatingHandler> handlerInstances = null;
- try
- {
- if (this.handlerFunc != null)
- {
- handlerInstances = this.handlerFunc.Invoke();
- if (handlerInstances != null)
- {
- foreach (DelegatingHandler handler in handlerInstances)
- {
- if (handler == null)
- {
- throw FxTrace.Exception.Argument("handlers", SR.GetString(SR.DelegatingHandlerArrayFromFuncContainsNullItem, delegatingHandlerType.Name, GetFuncDetails(this.handlerFunc)));
- }
- }
- }
- }
- else if (this.handlerCtors != null)
- {
- DelegatingHandler[] instances = new DelegatingHandler[this.handlerCtors.Length];
- for (int cnt = 0; cnt < this.handlerCtors.Length; cnt++)
- {
- instances[cnt] = (DelegatingHandler)this.handlerCtors[cnt].Invoke(Type.EmptyTypes);
- }
- handlerInstances = instances;
- }
- }
- catch (TargetInvocationException targetInvocationException)
- {
- throw FxTrace.Exception.AsError(targetInvocationException);
- }
- // Wire handlers up
- HttpMessageHandler pipeline = innerChannel;
- if (handlerInstances != null)
- {
- foreach (DelegatingHandler handler in handlerInstances)
- {
- if (handler.InnerHandler != null)
- {
- throw FxTrace.Exception.Argument("handlers", SR.GetString(SR.DelegatingHandlerArrayHasNonNullInnerHandler, delegatingHandlerType.Name, "InnerHandler", handler.GetType().Name));
- }
- handler.InnerHandler = pipeline;
- pipeline = handler;
- }
- }
- return pipeline;
- }
- static string GetFuncDetails(Func<IEnumerable<DelegatingHandler>> func)
- {
- Fx.Assert(func != null, "Func should not be null.");
- MethodInfo m = func.Method;
- Type t = m.DeclaringType;
- return string.Format(CultureInfo.InvariantCulture, "{0}.{1}", t.FullName, m.Name);
- }
- }
- }
|