/WCFWebApi/src/Microsoft.ApplicationServer.Http/Microsoft/ApplicationServer/Http/Dispatcher/UriTemplateHandler.cs

# · C# · 149 lines · 77 code · 18 blank · 54 comment · 13 complexity · 08b410d440e5f9df0112afea0f07efb4 MD5 · raw file

  1. // <copyright>
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. // </copyright>
  4. namespace Microsoft.ApplicationServer.Http.Dispatcher
  5. {
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Net.Http;
  9. using Microsoft.ApplicationServer.Http.Description;
  10. using Microsoft.Server.Common;
  11. /// <summary>
  12. /// A <see cref="HttpOperationHandler"/> that matches an input <see cref="Uri"/> against a
  13. /// given <see cref="UriTemplate"/> and outputs <see cref="UriTemplate"/> variable
  14. /// values as strings.
  15. /// </summary>
  16. public class UriTemplateHandler : HttpOperationHandler
  17. {
  18. /// <summary>
  19. /// Initializes a new instance of a <see cref="UriTemplateHandler"/> with the
  20. /// given <paramref name="baseAddress"/> and <paramref name="uriTemplate"/>.
  21. /// </summary>
  22. /// <param name="baseAddress">
  23. /// The base address to use when matching a <see cref="Uri"/> against the given <paramref name="uriTemplate"/>
  24. /// </param>
  25. /// <param name="uriTemplate">
  26. /// The <see cref="UriTemplate"/> to match against input <see cref="Uri">Uris</see>.
  27. /// </param>
  28. public UriTemplateHandler(Uri baseAddress, UriTemplate uriTemplate)
  29. {
  30. if (baseAddress == null)
  31. {
  32. throw Fx.Exception.ArgumentNull("baseAddress");
  33. }
  34. if (uriTemplate == null)
  35. {
  36. throw Fx.Exception.ArgumentNull("uriTemplate");
  37. }
  38. this.BaseAddress = baseAddress;
  39. this.UriTemplate = uriTemplate;
  40. }
  41. /// <summary>
  42. /// Gets the base address to use when matching a <see cref="Uri"/> against the <cref name="UriTemplate"/>.
  43. /// </summary>
  44. public Uri BaseAddress { get; private set; }
  45. /// <summary>
  46. /// Gets the <see cref="UriTemplate"/> to match against input <see cref="Uri"/> instances.
  47. /// </summary>
  48. public UriTemplate UriTemplate { get; private set; }
  49. /// <summary>
  50. /// Retrieves the collection of <see cref="HttpParameter"/> instances describing the
  51. /// input values for this <see cref="UriTemplateHandler"/>.
  52. /// </summary>
  53. /// <remarks>
  54. /// The <see cref="UriTemplateHandler"/> always returns a single input of
  55. /// <see cref="HttpParameter.RequestMessage"/>.
  56. /// </remarks>
  57. /// <returns>A collection that consists of just the <see cref="HttpParameter.RequestMessage"/>.</returns>
  58. protected override sealed IEnumerable<HttpParameter> OnGetInputParameters()
  59. {
  60. return new HttpParameter[] { HttpParameter.RequestMessage };
  61. }
  62. /// <summary>
  63. /// Retrieves the collection of <see cref="HttpParameter"/> instances describing the
  64. /// output values of this <see cref="UriTemplateHandler"/>.
  65. /// </summary>
  66. /// <remarks>
  67. /// The <see cref="UriTemplateHandler"/> always returns output <see cref="HttpParameter"/>
  68. /// instances in which the <see cref="HttpParameter.Name"/> is the <see cref="UriTemplateHandler.UriTemplate"/>
  69. /// variable and the <see cref="HttpParameter.ParameterType"/> is of type <see cref="String"/>.
  70. /// </remarks>
  71. /// <returns>The collection of <see cref="HttpParameter"/> instances.</returns>
  72. protected override sealed IEnumerable<HttpParameter> OnGetOutputParameters()
  73. {
  74. int numberOfVariables = this.UriTemplate.PathSegmentVariableNames.Count + this.UriTemplate.QueryValueVariableNames.Count;
  75. HttpParameter[] parameters = new HttpParameter[numberOfVariables];
  76. int i = 0;
  77. foreach (string name in this.UriTemplate.PathSegmentVariableNames)
  78. {
  79. parameters[i] = new HttpParameter(name, TypeHelper.StringType);
  80. i++;
  81. }
  82. foreach (string name in this.UriTemplate.QueryValueVariableNames)
  83. {
  84. parameters[i] = new HttpParameter(name, TypeHelper.StringType);
  85. i++;
  86. }
  87. return parameters;
  88. }
  89. /// <summary>
  90. /// Called to execute this <see cref="UriTemplateHandler"/>.
  91. /// </summary>
  92. /// <param name="input">
  93. /// The input values to handle, corresponding to the <see cref="HttpParameter"/>
  94. /// returned by <see cref="OnGetInputParameters"/>
  95. /// </param>
  96. /// <returns>
  97. /// The <see cref="UriTemplate"/> variable values from matching the <see cref="UriTemplate"/>
  98. /// agains the request <see cref="Uri"/>.
  99. /// </returns>
  100. protected override sealed object[] OnHandle(object[] input)
  101. {
  102. Fx.Assert(input != null, "The 'input' parameter should not be null.");
  103. Fx.Assert(input.Length == 1, "There should be one element in the 'input' array");
  104. HttpRequestMessage requestMessage = input[0] as HttpRequestMessage;
  105. if (requestMessage == null)
  106. {
  107. throw Fx.Exception.ArgumentNull(HttpParameter.RequestMessage.Name);
  108. }
  109. Uri uri = requestMessage.RequestUri;
  110. int numberOfParameters = this.OutputParameters.Count;
  111. object[] output = new object[numberOfParameters];
  112. if (uri != null)
  113. {
  114. UriTemplateMatch match = this.UriTemplate.Match(this.BaseAddress, uri);
  115. if (match == null)
  116. {
  117. throw Fx.Exception.AsError(
  118. new InvalidOperationException(
  119. Http.SR.UriTemplateDoesNotMatchUri(
  120. uri.ToString(),
  121. this.UriTemplate.ToString())));
  122. }
  123. for (int i = 0; i < numberOfParameters; i++)
  124. {
  125. output[i] = match.BoundVariables[i];
  126. }
  127. }
  128. return output;
  129. }
  130. }
  131. }