PageRenderTime 23ms CodeModel.GetById 7ms app.highlight 10ms RepoModel.GetById 2ms app.codeStats 0ms

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