HttpMessageHandlerFactory.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. // <copyright>
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. // </copyright>
  4. namespace System.ServiceModel.Channels
  5. {
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Collections.ObjectModel;
  9. using System.Configuration;
  10. using System.Globalization;
  11. using System.Net.Http;
  12. using System.Reflection;
  13. using System.Runtime;
  14. using System.Runtime.CompilerServices;
  15. using System.Security;
  16. using System.Security.Permissions;
  17. using System.ServiceModel.Configuration;
  18. /// <summary>
  19. /// Default HTTP message handler factory used by <see cref="HttpChannelListener"/> upon creation of an <see cref="HttpMessageHandler"/>
  20. /// for instantiating a set of HTTP message handler types using their default constructors.
  21. /// For more complex initialization scenarios, derive from <see cref="HttpMessageHandlerFactory"/>
  22. /// and override the <see cref="HttpMessageHandlerFactory.OnCreate"/> method.
  23. /// </summary>
  24. public class HttpMessageHandlerFactory
  25. {
  26. static readonly Type delegatingHandlerType = typeof(DelegatingHandler);
  27. Type[] httpMessageHandlers;
  28. ConstructorInfo[] handlerCtors;
  29. Func<IEnumerable<DelegatingHandler>> handlerFunc;
  30. /// <summary>
  31. /// Initializes a new instance of the <see cref="HttpMessageHandlerFactory"/> class given
  32. /// a set of HTTP message handler types to instantiate using their default constructors.
  33. /// </summary>
  34. /// <param name="handlers">An ordered list of HTTP message handler types to be invoked as part of an
  35. /// <see cref="HttpMessageHandler"/> instance.
  36. /// HTTP message handler types must derive from <see cref="DelegatingHandler"/> and have a public constructor
  37. /// taking exactly one argument of type <see cref="HttpMessageHandler"/>. The handlers are invoked in a
  38. /// bottom-up fashion in the incoming path and top-down in the outgoing path. That is, the last entry is called first
  39. /// for an incoming request messasge but invoked last for an outgoing response message.</param>
  40. [PermissionSet(SecurityAction.Demand, Unrestricted = true), SecuritySafeCritical]
  41. [MethodImpl(MethodImplOptions.NoInlining)]
  42. public HttpMessageHandlerFactory(params Type[] handlers)
  43. {
  44. if (handlers == null)
  45. {
  46. throw FxTrace.Exception.ArgumentNull("handlers");
  47. }
  48. if (handlers.Length == 0)
  49. {
  50. throw FxTrace.Exception.Argument("handlers", SR.GetString(SR.InputTypeListEmptyError));
  51. }
  52. this.handlerCtors = new ConstructorInfo[handlers.Length];
  53. for (int cnt = 0; cnt < handlers.Length; cnt++)
  54. {
  55. Type handler = handlers[cnt];
  56. if (handler == null)
  57. {
  58. throw FxTrace.Exception.Argument(
  59. string.Format(CultureInfo.InvariantCulture, "handlers[<<{0}>>]", cnt),
  60. SR.GetString(SR.HttpMessageHandlerTypeNotSupported, "null", delegatingHandlerType.Name));
  61. }
  62. if (!delegatingHandlerType.IsAssignableFrom(handler) || handler.IsAbstract)
  63. {
  64. throw FxTrace.Exception.Argument(
  65. string.Format(CultureInfo.InvariantCulture, "handlers[<<{0}>>]", cnt),
  66. SR.GetString(SR.HttpMessageHandlerTypeNotSupported, handler.Name, delegatingHandlerType.Name));
  67. }
  68. ConstructorInfo ctorInfo = handler.GetConstructor(Type.EmptyTypes);
  69. if (ctorInfo == null)
  70. {
  71. throw FxTrace.Exception.Argument(
  72. string.Format(CultureInfo.InvariantCulture, "handlers[<<{0}>>]", cnt),
  73. SR.GetString(SR.HttpMessageHandlerTypeNotSupported, handler.Name, delegatingHandlerType.Name));
  74. }
  75. this.handlerCtors[cnt] = ctorInfo;
  76. }
  77. this.httpMessageHandlers = handlers;
  78. }
  79. /// <summary>
  80. /// Initializes a new instance of the <see cref="HttpMessageHandlerFactory"/> class given
  81. /// a function to create a set of <see cref="DelegatingHandler"/> instances.
  82. /// </summary>
  83. /// <param name="handlers">A function to generate an ordered list of <see cref="DelegatingHandler"/> instances
  84. /// to be invoked as part of an <see cref="HttpMessageHandler"/> instance.
  85. /// The handlers are invoked in a bottom-up fashion in the incoming path and top-down in the outgoing path. That is,
  86. /// the last entry is called first for an incoming request messasge but invoked last for an outgoing response message.</param>
  87. [PermissionSet(SecurityAction.Demand, Unrestricted = true), SecuritySafeCritical]
  88. [MethodImpl(MethodImplOptions.NoInlining)]
  89. public HttpMessageHandlerFactory(Func<IEnumerable<DelegatingHandler>> handlers)
  90. {
  91. if (handlers == null)
  92. {
  93. throw FxTrace.Exception.ArgumentNull("handlers");
  94. }
  95. this.handlerFunc = handlers;
  96. }
  97. /// <summary>
  98. /// Initializes a new instance of the <see cref="HttpMessageHandlerFactory"/> class.
  99. /// </summary>
  100. [PermissionSet(SecurityAction.Demand, Unrestricted = true), SecuritySafeCritical]
  101. [MethodImpl(MethodImplOptions.NoInlining)]
  102. protected HttpMessageHandlerFactory()
  103. {
  104. }
  105. /// <summary>
  106. /// Creates an instance of an <see cref="HttpMessageHandler"/> using the HTTP message handlers
  107. /// provided in the constructor.
  108. /// </summary>
  109. /// <param name="innerChannel">The inner channel represents the destination of the HTTP message channel.</param>
  110. /// <returns>The HTTP message channel.</returns>
  111. [PermissionSet(SecurityAction.Demand, Unrestricted = true), SecuritySafeCritical]
  112. [MethodImpl(MethodImplOptions.NoInlining)]
  113. public HttpMessageHandler Create(HttpMessageHandler innerChannel)
  114. {
  115. if (innerChannel == null)
  116. {
  117. throw FxTrace.Exception.ArgumentNull("innerChannel");
  118. }
  119. return this.OnCreate(innerChannel);
  120. }
  121. internal static HttpMessageHandlerFactory CreateFromConfigurationElement(HttpMessageHandlerFactoryElement configElement)
  122. {
  123. Fx.Assert(configElement != null, "configElement should not be null.");
  124. if (!string.IsNullOrWhiteSpace(configElement.Type))
  125. {
  126. if (configElement.Handlers != null && configElement.Handlers.Count > 0)
  127. {
  128. throw FxTrace.Exception.AsError(new ConfigurationErrorsException(SR.GetString(SR.HttpMessageHandlerFactoryConfigInvalid_WithBothTypeAndHandlerList, ConfigurationStrings.MessageHandlerFactory, ConfigurationStrings.Type, ConfigurationStrings.Handlers)));
  129. }
  130. Type factoryType = HttpChannelUtilities.GetTypeFromAssembliesInCurrentDomain(configElement.Type);
  131. if (factoryType == null)
  132. {
  133. throw FxTrace.Exception.AsError(new ConfigurationErrorsException(SR.GetString(SR.CanNotLoadTypeGotFromConfig, configElement.Type)));
  134. }
  135. if (!typeof(HttpMessageHandlerFactory).IsAssignableFrom(factoryType) || factoryType.IsAbstract)
  136. {
  137. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ConfigurationErrorsException(
  138. SR.GetString(
  139. SR.WebSocketElementConfigInvalidHttpMessageHandlerFactoryType,
  140. typeof(HttpMessageHandlerFactory).Name,
  141. factoryType,
  142. typeof(HttpMessageHandlerFactory).AssemblyQualifiedName)));
  143. }
  144. return Activator.CreateInstance(factoryType) as HttpMessageHandlerFactory;
  145. }
  146. else
  147. {
  148. if (configElement.Handlers == null || configElement.Handlers.Count == 0)
  149. {
  150. return null;
  151. }
  152. Type[] handlerList = new Type[configElement.Handlers.Count];
  153. for (int i = 0; i < configElement.Handlers.Count; i++)
  154. {
  155. Type handlerType = HttpChannelUtilities.GetTypeFromAssembliesInCurrentDomain(configElement.Handlers[i].Type);
  156. if (handlerType == null)
  157. {
  158. throw FxTrace.Exception.AsError(new ConfigurationErrorsException(SR.GetString(SR.CanNotLoadTypeGotFromConfig, configElement.Handlers[i].Type)));
  159. }
  160. handlerList[i] = handlerType;
  161. }
  162. try
  163. {
  164. return new HttpMessageHandlerFactory(handlerList);
  165. }
  166. catch (ArgumentException ex)
  167. {
  168. throw FxTrace.Exception.AsError(new ConfigurationErrorsException(ex.Message, ex));
  169. }
  170. }
  171. }
  172. internal HttpMessageHandlerFactoryElement GenerateConfigurationElement()
  173. {
  174. if (this.handlerFunc != null)
  175. {
  176. throw FxTrace.Exception.AsError(new InvalidOperationException(SR.GetString(SR.HttpMessageHandlerFactoryWithFuncCannotGenerateConfig, typeof(HttpMessageHandlerFactory).Name, typeof(Func<IEnumerable<DelegatingHandler>>).Name)));
  177. }
  178. Type thisType = this.GetType();
  179. if (thisType != typeof(HttpMessageHandlerFactory))
  180. {
  181. return new HttpMessageHandlerFactoryElement
  182. {
  183. Type = thisType.AssemblyQualifiedName
  184. };
  185. }
  186. else
  187. {
  188. if (this.httpMessageHandlers != null)
  189. {
  190. DelegatingHandlerElementCollection handlerCollection = new DelegatingHandlerElementCollection();
  191. for (int i = 0; i < this.httpMessageHandlers.Length; i++)
  192. {
  193. handlerCollection.Add(new DelegatingHandlerElement(this.httpMessageHandlers[i]));
  194. }
  195. return new HttpMessageHandlerFactoryElement
  196. {
  197. Handlers = handlerCollection
  198. };
  199. }
  200. }
  201. return null;
  202. }
  203. /// <summary>
  204. /// Creates an instance of an <see cref="HttpMessageHandler"/> using the HTTP message handlers
  205. /// provided in the constructor.
  206. /// </summary>
  207. /// <param name="innerChannel">The inner channel represents the destination of the HTTP message channel.</param>
  208. /// <returns>The HTTP message channel.</returns>
  209. protected virtual HttpMessageHandler OnCreate(HttpMessageHandler innerChannel)
  210. {
  211. if (innerChannel == null)
  212. {
  213. throw FxTrace.Exception.ArgumentNull("innerChannel");
  214. }
  215. // Get handlers either by constructing types or by calling Func
  216. IEnumerable<DelegatingHandler> handlerInstances = null;
  217. try
  218. {
  219. if (this.handlerFunc != null)
  220. {
  221. handlerInstances = this.handlerFunc.Invoke();
  222. if (handlerInstances != null)
  223. {
  224. foreach (DelegatingHandler handler in handlerInstances)
  225. {
  226. if (handler == null)
  227. {
  228. throw FxTrace.Exception.Argument("handlers", SR.GetString(SR.DelegatingHandlerArrayFromFuncContainsNullItem, delegatingHandlerType.Name, GetFuncDetails(this.handlerFunc)));
  229. }
  230. }
  231. }
  232. }
  233. else if (this.handlerCtors != null)
  234. {
  235. DelegatingHandler[] instances = new DelegatingHandler[this.handlerCtors.Length];
  236. for (int cnt = 0; cnt < this.handlerCtors.Length; cnt++)
  237. {
  238. instances[cnt] = (DelegatingHandler)this.handlerCtors[cnt].Invoke(Type.EmptyTypes);
  239. }
  240. handlerInstances = instances;
  241. }
  242. }
  243. catch (TargetInvocationException targetInvocationException)
  244. {
  245. throw FxTrace.Exception.AsError(targetInvocationException);
  246. }
  247. // Wire handlers up
  248. HttpMessageHandler pipeline = innerChannel;
  249. if (handlerInstances != null)
  250. {
  251. foreach (DelegatingHandler handler in handlerInstances)
  252. {
  253. if (handler.InnerHandler != null)
  254. {
  255. throw FxTrace.Exception.Argument("handlers", SR.GetString(SR.DelegatingHandlerArrayHasNonNullInnerHandler, delegatingHandlerType.Name, "InnerHandler", handler.GetType().Name));
  256. }
  257. handler.InnerHandler = pipeline;
  258. pipeline = handler;
  259. }
  260. }
  261. return pipeline;
  262. }
  263. static string GetFuncDetails(Func<IEnumerable<DelegatingHandler>> func)
  264. {
  265. Fx.Assert(func != null, "Func should not be null.");
  266. MethodInfo m = func.Method;
  267. Type t = m.DeclaringType;
  268. return string.Format(CultureInfo.InvariantCulture, "{0}.{1}", t.FullName, m.Name);
  269. }
  270. }
  271. }