public sealed override void ProcessRequest(HttpContext context) { _currentContext = context; if (ShouldValidateSession) { if (context.Request.AppRelativeCurrentExecutionFilePath.Replace("~", string.Empty).ToLower() != LogIn.ToLower()) { int userCode; ApplicationType applicationType; string session = context.Request.Headers[SessionHeader]; if (String.IsNullOrEmpty(session) || !IsSessionValid(session, out userCode, out applicationType)) { throw new HttpException("Invalid session information", (int)HttpStatusCode.Forbidden); } else { context.Request.Headers.Add("edge-user-id", userCode.ToString()); } } } // TODO -later: permissions per request MethodInfo[] methods = this.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); MethodInfo foundMethod = null; UriMappingAttribute foundAttribute = null; Match foundMatch = null; foreach (MethodInfo method in methods) { // Get only method with the 'UriMapping' attribute UriMappingAttribute attr = (UriMappingAttribute)Attribute.GetCustomAttribute(method, typeof(UriMappingAttribute)); if (attr == null) { continue; } if (attr.Regex == null) { // Assign the regex to the attribute for later use attr.Regex = BuildRegex(method, attr); } if (!string.IsNullOrEmpty(attr.Regex.ToString())) { string netopath = context.Request.Url.PathAndQuery.Remove(0, context.Request.ApplicationPath.Length); if (!netopath.StartsWith("/")) { netopath = '/' + netopath; } Match match = attr.Regex.Match(netopath); if (match.Success) { if (context.Request.HttpMethod == attr.Method) { foundMethod = method; foundMatch = match; foundAttribute = attr; break; } } } } if (foundMethod == null || foundMatch == null) { throw new UriTemplateException("There is no method set up to handle the specified path.", context.Request.Url.PathAndQuery, HttpStatusCode.NotFound); } // Build a list of method arguments ParameterInfo[] methodParams = foundMethod.GetParameters(); object[] methodArgs = new object[methodParams.Length]; for (int i = 0; i < methodParams.Length; i++) { ParameterInfo param = methodParams[i]; object paramVal; if (param.Name == foundAttribute.BodyParameter) { // Handle POST body deserialization // TODO: allow deserializing as stream paramVal = HttpManager.DeserializeFromInput(context, param.ParameterType); } else { // foundMatch.Groups[param.Name] will always find a group because if it were empty - the regex would not have succeeded string rawValue = foundMatch.Groups[param.Name].Value; paramVal = Convert.ChangeType(rawValue, param.ParameterType); } methodArgs[i] = paramVal; } // Run the M**********R object val = foundMethod.Invoke(this, methodArgs); // return as JSON for now HttpManager.SetResponse(context, System.Net.HttpStatusCode.OK, val, "text/plain"); }
private static Regex BuildRegex(MethodInfo method, UriMappingAttribute attr) { Regex targetRegex; MatchCollection paramMatches = FindParametersRegex.Matches(attr.Template); if (paramMatches.Count < 1) { targetRegex = new Regex(string.Format(@"^{1}{0}$", attr.Template, attr.Template.StartsWith("/") ? string.Empty : "/" ), RegexOptions.IgnoreCase); } else { // Always start URLs with a leading slash string targetRegexPattern = "^" + (attr.Template.StartsWith("/") ? string.Empty : "/"); ParameterInfo[] parameters = method.GetParameters(); int lastIndex = 0; foreach (Match m in paramMatches) { targetRegexPattern += Regex.Escape(string.Format("{0}", attr.Template.Substring(lastIndex, m.Index - lastIndex))); lastIndex = m.Index + m.Value.Length; ParameterInfo foundParam = null; foreach (ParameterInfo param in parameters) { string paramName = m.Groups[1].Value; // get the param name if (param.Name == paramName) { foundParam = param; break; } } string paramExpression; if (foundParam == null) { paramExpression = m.Value; } else { string typeExpression; if (!TypeExpressions.TryGetValue(foundParam.ParameterType, out typeExpression)) { throw new UriTemplateException(foundParam.Name, System.Net.HttpStatusCode.NotFound); } // we found a matching parameter! paramExpression = "(?<" + foundParam.Name + ">" + typeExpression + ")"; } targetRegexPattern += paramExpression; } if (attr.Template.Length > lastIndex) { targetRegexPattern += Regex.Escape(attr.Template.Substring(lastIndex, attr.Template.Length - lastIndex)); } targetRegex = new Regex(targetRegexPattern + "$"); } return(targetRegex); }