public static string GetEndpointInfoVariables(HttpController controller, HttpEndpoint endpoint) { var controllerVar = $@"var {Constants.ControllerRouteReserved} = ""{endpoint.Parent.Name}"";"; var actionVar = $@"var {Constants.ActionRouteReserved} = ""{endpoint.Name}"";"; if (!endpoint.GetFullRoute(controller).Contains($"[{Constants.ControllerRouteReserved}]")) { controllerVar = null; } if (!endpoint.GetFullRoute(controller).Contains($"[{Constants.ActionRouteReserved}]")) { actionVar = null; } return ($@"{controllerVar} {actionVar}"); }
public static string GetRoute(HttpController controller, HttpEndpoint endpoint, bool async) { const string RouteParseRegex = @"{([^}]+)}"; string routeUnformatted = endpoint.GetFullRoute(controller); var patterns = Regex.Matches(routeUnformatted, RouteParseRegex); var routeParameters = endpoint.GetRouteParameters().ToList(); var queryParameters = endpoint.GetQueryParameters().ToList(); foreach (var group in patterns) { Match match = group as Match; string filtered = match.Value.Replace("{", "").Replace("}", ""); string[] split = filtered.Split(new char[] { ':' }); string variable = split[0]; if (!routeParameters.Any(x => x.Name.Equals(variable, StringComparison.CurrentCultureIgnoreCase))) { throw new Exception($"{variable} is missing from passed in parameters. Please check your route."); } var parameter = routeParameters.SingleOrDefault(x => x.Name.Equals(variable, StringComparison.CurrentCultureIgnoreCase)); if (Helpers.IsRoutableType(parameter.Type)) { routeUnformatted = routeUnformatted.Replace(match.Value, $"{{{Helpers.GetRouteStringTransform(parameter.Name, parameter.Type)}}}"); } } if (queryParameters.Any()) { string queryString = $"?{string.Join("&", queryParameters.Select(x => WriteQueryParameter(x, async)))}"; routeUnformatted += $"{queryString}"; } routeUnformatted = routeUnformatted.Replace($"[{Constants.ControllerRouteReserved}]", $"{{{Constants.ControllerRouteReserved}}}"); routeUnformatted = routeUnformatted.Replace($"[{Constants.ActionRouteReserved}]", $"{{{Constants.ActionRouteReserved}}}"); return(routeUnformatted); }
private static HttpEndpoint ReadMethodAsHttpEndpoint(HttpController parent, MethodDeclarationSyntax syntax) { var attributes = syntax.DescendantNodes().OfType <AttributeListSyntax>().SelectMany(x => x.Attributes).ToList(); var endpoint = new HttpEndpoint(parent); endpoint.Name = syntax.Identifier.ValueText.CleanMethodName(); endpoint.Virtual = syntax.Modifiers.Any(x => x.Text == "virtual"); endpoint.Override = syntax.Modifiers.Any(x => x.Text == "override"); endpoint.New = syntax.Modifiers.Any(x => x.Text == "new"); //Ignore generator attribute endpoint.Ignored = attributes.SingleOrDefault(x => x.Name.ToFullString().MatchesAttribute(nameof(NotGeneratedAttribute))) != null; //Route Attribute var routeAttribute = attributes.SingleOrDefault(x => x.Name.ToFullString().MatchesAttribute(nameof(RouteAttribute))); if (routeAttribute != null) //Fetch route from RouteAttribute { endpoint.Route = new HttpRoute(routeAttribute.ArgumentList.Arguments.ToFullString().Replace("\"", "").Trim()); } //HTTP Attribute var knownHttpAttributes = new List <string> { $"{Constants.Http}{HttpAttributeType.Delete}", $"{Constants.Http}{HttpAttributeType.Get}", $"{Constants.Http}{HttpAttributeType.Patch}", $"{Constants.Http}{HttpAttributeType.Post}", $"{Constants.Http}{HttpAttributeType.Put}", }; var httpAttribute = attributes.SingleOrDefault(x => knownHttpAttributes.Any(y => x.Name.ToFullString().MatchesAttribute(y))); if (httpAttribute == null) { endpoint.Ignored = true; } else { var httpType = (HttpAttributeType)Enum.Parse(typeof(HttpAttributeType), httpAttribute.Name .ToFullString() .Replace(Constants.Http, "") .Replace(Constants.Attribute, "")); endpoint.HttpType = Helpers.HttpMethodFromEnum(httpType); } if (endpoint.Route == null && httpAttribute?.ArgumentList != null) //If Route was never fetched from RouteAttribute or if they used the Http(template) override { endpoint.Route = new HttpRoute(httpAttribute.ArgumentList.Arguments.ToFullString().Replace("\"", "").Trim()); } //Ignore method if it doesn't have a route or http attribute if (endpoint.Route == null && httpAttribute == null) { endpoint.Ignored = true; return(endpoint); } //Obsolete Attribute var obsoleteAttribute = attributes.SingleOrDefault(x => x.Name.ToFullString().MatchesAttribute(nameof(ObsoleteAttribute))); if (obsoleteAttribute != null) { endpoint.Obsolete = true; endpoint.ObsoleteMessage = obsoleteAttribute.ArgumentList.Arguments.ToFullString().Replace("\"", "").Trim(); } //Authorize Attribute endpoint.IsSecured = attributes.SingleOrDefault(x => x.Name.ToFullString().MatchesAttribute(nameof(AuthorizeAttribute))) != null; //Response types var responseTypes = attributes.Where(x => x.Name.ToFullString().MatchesAttribute(nameof(ProducesResponseTypeAttribute))); var responses = responseTypes.Select(x => new ResponseTypeDefinition(x)).ToList(); responses.Add(new ResponseTypeDefinition(true)); endpoint.ResponseTypes = responses.Select(x => new ResponseType(x.Type, Helpers.EnumParse <HttpStatusCode>(x.StatusValue))).ToList(); var duplicateResponseTypes = endpoint.GetResponseTypes().GroupBy(x => x.Status).Where(x => x.Count() > 1).ToList(); if (duplicateResponseTypes.Any()) { throw new NotSupportedException($"Endpoint has multiple response types of the same status defined. {string.Join(", ", duplicateResponseTypes.Select(x => x.Key?.ToString()))}"); } //Add after so we don't get duplicate error from the null Status endpoint.ResponseTypes.Add(new ExceptionResponseType()); var parameters = syntax.ParameterList.Parameters.Select(x => new ParameterDefinition(x, endpoint.GetFullRoute(parent))).ToList(); var routeParams = parameters.Where(x => x.Options.FromRoute).Select(x => new RouteParameter(x.RouteName, x.Type, x.Default)).ToList(); var queryParams = parameters.Where(x => x.Options.FromQuery).Select(x => new QueryParameter(x.Options.QueryName, x.Type, x.Default, x.Options.QueryObject)).ToList(); var bodyParams = parameters.Where(x => x.Options.FromBody).Select(x => new BodyParameter(x.Name, x.Type, x.Default)).SingleOrDefault(); endpoint.Parameters = routeParams.Cast <IParameter>().Union(queryParams).Union(new List <IParameter> { bodyParams }).NotNull().ToList(); endpoint.Parameters.Add(new CancellationTokenModifier()); endpoint.Parameters.Add(new CookieModifier()); endpoint.Parameters.Add(new HeadersModifier()); endpoint.Parameters.Add(new TimeoutModifier()); if (endpoint.IsSecured) { endpoint.Parameters.Add(new SecurityModifier()); } var parameterHeaders = attributes.Where(x => x.Name.ToFullString().MatchesAttribute(nameof(HeaderParameterAttribute))) .Select(x => new ParameterHeaderDefinition(x)) .ToList(); endpoint.ParameterHeader = parameterHeaders.Select(x => new ParameterHeader(x.Name, x.Type, x.DefaultValue)).ToList(); var headers = attributes.Where(x => x.Name.ToFullString().MatchesAttribute(nameof(IncludeHeaderAttribute))) .Select(x => new HeaderDefinition(x)) .ToList(); endpoint.ConstantHeader = headers.Select(x => new ConstantHeader(x.Name, x.Value)).ToList(); var rawReturnType = syntax.ReturnType?.ToFullString(); HashSet <string> returnContainerTypes = new HashSet <string>() { typeof(ValueTask).FullName, typeof(Task).FullName, typeof(ActionResult).FullName }; var returnType = Helpers.GetTypeFromString(rawReturnType.Trim()); while (returnContainerTypes.Any(x => Helpers.IsType(x, returnType?.Name))) { returnType = returnType.Arguments.SingleOrDefault(); } if (Helpers.IsType(typeof(IActionResult).FullName, returnType?.Name)) { returnType = null; } if (returnType?.Name == "void" || (Helpers.IsType(typeof(Task).FullName, returnType?.Name) && (!returnType?.Arguments.Any() ?? false))) { returnType = null; } HashSet <string> fileResults = new HashSet <string>() { nameof(PhysicalFileResult), nameof(FileResult), nameof(FileContentResult), nameof(FileStreamResult), nameof(VirtualFileResult) }; if (fileResults.Any(x => Helpers.IsType(x, returnType?.Name))) { returnType = new Helpers.TypeString(typeof(Stream).FullName); endpoint.ReturnsStream = true; } rawReturnType = returnType?.ToString(); endpoint.ReturnType = rawReturnType; var duplicateParameters = endpoint.GetParametersWithoutResponseTypes().GroupBy(x => x.Name).Where(x => x.Count() > 1).ToList(); if (duplicateParameters.Any()) { throw new NotSupportedException($"Endpoint has multiple parameters of the same name defined. {string.Join(", ", duplicateParameters.Select(x => x.Key?.ToString()))}"); } return(endpoint); }