private IRpcMethodInfo[] GetMatchingMethods(RpcRequestSignature requestSignature, IReadOnlyList <IRpcMethodInfo> methods) { IRpcMethodInfo[] methodsWithSameName = ArrayPool <IRpcMethodInfo> .Shared.Rent(methods.Count); try { //Case insenstive check for hybrid approach. Will check for case sensitive if there is ambiguity int methodsWithSameNameCount = 0; for (int i = 0; i < methods.Count; i++) { IRpcMethodInfo methodInfo = methods[i]; if (RpcUtil.NamesMatch(methodInfo.Name.AsSpan(), requestSignature.GetMethodName().Span)) { methodsWithSameName[methodsWithSameNameCount++] = methodInfo; } } if (methodsWithSameNameCount < 1) { return(Array.Empty <IRpcMethodInfo>()); } return(this.FilterBySimilarParams(requestSignature, methodsWithSameName.AsSpan(0, methodsWithSameNameCount))); } finally { ArrayPool <IRpcMethodInfo> .Shared.Return(methodsWithSameName, clearArray : false); } }
public string GetSummaryForMethod(IRpcMethodInfo methodInfo) { var methodNode = this.xpathNavigator.SelectSingleNode($"/doc/members/member[@name='{methodInfo.Name}']"); var summaryNode = methodNode?.SelectSingleNode("summary"); return(summaryNode != null?XmlCommentsTextHelper.Humanize(summaryNode.InnerXml) : string.Empty); }
public RpcEndpointBuilder AddMethod(MethodInfo methodInfo, RpcPath?path = null) { IRpcMethodInfo rpcMethodInfo = DefaultRpcMethodInfo.FromMethodInfo(methodInfo); this.Add(path, rpcMethodInfo); return(this); }
private IRpcMethodInfo[] FilterMatchesByCaseSensitiveMethod(RpcRequestSignature requestSignature, Span <IRpcMethodInfo> matches) { //Try to remove ambiguity with case sensitive check IRpcMethodInfo[] caseSensitiveMatches = ArrayPool <IRpcMethodInfo> .Shared.Rent(matches.Length); try { int caseSensitiveCount = 0; for (int i = 0; i < matches.Length; i++) { IRpcMethodInfo m = matches[i]; Memory <char> requestMethodName = requestSignature.GetMethodName(); if (m.Name.Length == requestMethodName.Length) { if (!RpcUtil.NamesMatch(m.Name.AsSpan(), requestMethodName.Span)) { //TODO do we care about the case where 2+ parameters have very similar names and types? continue; } caseSensitiveMatches[caseSensitiveCount++] = m; } } return(caseSensitiveMatches.AsSpan(0, caseSensitiveCount).ToArray()); } finally { ArrayPool <IRpcMethodInfo> .Shared.Return(caseSensitiveMatches, clearArray : false); } }
private IRpcMethodInfo[] FilterBySimilarParams(RpcRequestSignature requestSignature, Span <IRpcMethodInfo> methodsWithSameName) { IRpcMethodInfo[] potentialMatches = ArrayPool <IRpcMethodInfo> .Shared.Rent(methodsWithSameName.Length); try { int potentialMatchCount = 0; for (int i = 0; i < methodsWithSameName.Length; i++) { IRpcMethodInfo m = methodsWithSameName[i]; bool isMatch = this.ParametersMatch(requestSignature, m.Parameters); if (isMatch) { potentialMatches[potentialMatchCount++] = m; } } if (potentialMatchCount <= 1) { return(potentialMatches.AsSpan(0, potentialMatchCount).ToArray()); } return(this.FilterMatchesByCaseSensitiveMethod(requestSignature, potentialMatches.AsSpan(0, potentialMatchCount))); } finally { ArrayPool <IRpcMethodInfo> .Shared.Return(potentialMatches, clearArray : false); } }
public async Task <bool> IsAuthorizedAsync(IRpcMethodInfo methodInfo) { if (methodInfo.AuthorizeDataList.Any()) { if (methodInfo.AllowAnonymous) { this.logger.SkippingAuth(); } else { this.logger.RunningAuth(); AuthorizationResult authResult = await this.CheckAuthorize(methodInfo.AuthorizeDataList); if (authResult.Succeeded) { this.logger.AuthSuccessful(); } else { this.logger.AuthFailed(); return(false); } } } else { this.logger.NoConfiguredAuth(); } return(true); }
private OpenApiOperation GetOpenApiOperation(string key, IRpcMethodInfo methodInfo, SchemaRepository schemaRepository) { string methodAnnotation = this.xmlDocumentationService.GetSummaryForMethod(methodInfo); Type trueReturnType = this.GetReturnType(methodInfo.RawReturnType); return(new OpenApiOperation() { Tags = new List <OpenApiTag>(), Summary = methodAnnotation, RequestBody = this.GetOpenApiRequestBody(key, methodInfo, schemaRepository), Responses = this.GetOpenApiResponses(key, trueReturnType, schemaRepository) }); }
public string GetMethodParameterExample(IRpcMethodInfo methodInfo, IRpcParameterInfo parameterInfo) { var paramNode = this.xpathNavigator.SelectSingleNode( $"/doc/members/member[@name='{methodInfo.Name}']/param[@name='{parameterInfo.Name}']"); if (paramNode == null) { return(string.Empty); } var example = paramNode.GetAttribute("example", ""); return(example); }
private OpenApiRequestBody GetOpenApiRequestBody(string key, IRpcMethodInfo methodInfo, SchemaRepository schemaRepository) { return(new OpenApiRequestBody() { Content = new Dictionary <string, OpenApiMediaType>() { ["application/json"] = new OpenApiMediaType() { Schema = this.GetBodyParamsSchema(key, schemaRepository, methodInfo) } } }); }
public void GetMatchingMethod_GuidParameter_Match() { string methodName = nameof(MethodMatcherController.GuidTypeMethod); DefaultRequestMatcher matcher = this.GetMatcher(path: typeof(MethodMatcherController).GetTypeInfo().Name); var requestSignature = RpcRequestSignature.Create(methodName, new[] { RpcParameterType.String }); IRpcMethodInfo methodInfo = matcher.GetMatchingMethod(requestSignature); Assert.NotNull(methodInfo); Assert.Equal(methodName, methodInfo.Name); Assert.Single(methodInfo.Parameters); Assert.False(methodInfo.Parameters[0].IsOptional); Assert.Equal(typeof(Guid), methodInfo.Parameters[0].RawType); Assert.Equal(RpcParameterType.Object, methodInfo.Parameters[0].Type); Assert.Equal("guid", methodInfo.Parameters[0].Name); }
public void GetMatchingMethod_WithRpcRoute() { string methodName = nameof(MethodMatcherController.GuidTypeMethod); RpcRequestSignature requestSignature = RpcRequestSignature.Create(methodName, new[] { RpcParameterType.String }); DefaultRequestMatcher path1Matcher = this.GetMatcher(path: typeof(MethodMatcherController).GetTypeInfo().Name); IRpcMethodInfo path1Match = path1Matcher.GetMatchingMethod(requestSignature); Assert.NotNull(path1Match); DefaultRequestMatcher path2Matcher = this.GetMatcher(path: typeof(MethodMatcherDuplicatesController).GetTypeInfo().Name); IRpcMethodInfo path2Match = path2Matcher.GetMatchingMethod(requestSignature); Assert.NotNull(path2Match); Assert.NotSame(path1Match, path2Match); }
public void GetMatchingMethod_SimpleMulitParam_DictMatch() { DefaultRequestMatcher matcher = this.GetMatcher(path: typeof(MethodMatcherController).GetTypeInfo().Name); var parameters = new Dictionary <string, RpcParameterType> { { "a", RpcParameterType.Number }, { "b", RpcParameterType.Boolean }, { "c", RpcParameterType.String }, { "d", RpcParameterType.Object }, { "e", RpcParameterType.Null } }; string methodName = nameof(MethodMatcherController.SimpleMulitParam); var requestSignature = RpcRequestSignature.Create(methodName, parameters); IRpcMethodInfo methodInfo = matcher.GetMatchingMethod(requestSignature); Assert.NotNull(methodInfo); Assert.Equal(methodName, methodInfo.Name); Assert.Equal(5, methodInfo.Parameters.Count); Assert.False(methodInfo.Parameters[0].IsOptional); Assert.Equal(typeof(int), methodInfo.Parameters[0].RawType); Assert.Equal(RpcParameterType.Number, methodInfo.Parameters[0].Type); Assert.Equal("a", methodInfo.Parameters[0].Name); Assert.False(methodInfo.Parameters[1].IsOptional); Assert.Equal(typeof(bool), methodInfo.Parameters[1].RawType); Assert.Equal(RpcParameterType.Boolean, methodInfo.Parameters[1].Type); Assert.Equal("b", methodInfo.Parameters[1].Name); Assert.False(methodInfo.Parameters[2].IsOptional); Assert.Equal(typeof(string), methodInfo.Parameters[2].RawType); Assert.Equal(RpcParameterType.String, methodInfo.Parameters[2].Type); Assert.Equal("c", methodInfo.Parameters[2].Name); Assert.False(methodInfo.Parameters[3].IsOptional); Assert.Equal(typeof(object), methodInfo.Parameters[3].RawType); Assert.Equal(RpcParameterType.Object, methodInfo.Parameters[3].Type); Assert.Equal("d", methodInfo.Parameters[3].Name); Assert.True(methodInfo.Parameters[4].IsOptional); Assert.Equal(typeof(int?), methodInfo.Parameters[4].RawType); Assert.Equal(RpcParameterType.Object, methodInfo.Parameters[4].Type); Assert.Equal("e", methodInfo.Parameters[4].Name); }
public void GetMatchingMethod_ListParam_Match() { DefaultRequestMatcher matcher = this.GetMatcher(path: typeof(MethodMatcherController).GetTypeInfo().Name); RpcParameterType[] parameters = new[] { RpcParameterType.Object }; string methodName = nameof(MethodMatcherController.List); var requestSignature = RpcRequestSignature.Create(methodName, parameters); IRpcMethodInfo methodInfo = matcher.GetMatchingMethod(requestSignature); Assert.NotNull(methodInfo); Assert.Equal(methodName, methodInfo.Name); Assert.Single(methodInfo.Parameters); Assert.False(methodInfo.Parameters[0].IsOptional); Assert.Equal(typeof(List <string>), methodInfo.Parameters[0].RawType); Assert.Equal(RpcParameterType.Object, methodInfo.Parameters[0].Type); Assert.Equal("values", methodInfo.Parameters[0].Name); }
public void GetMatchingMethod_CulturallyInvariantComparison() { DefaultRequestMatcher matcher = this.GetMatcher(path: typeof(MethodMatcherController).GetTypeInfo().Name); RpcParameterType[] parameters = Array.Empty <RpcParameterType>(); string methodName = nameof(MethodMatcherController.IsLunchTime); // Use lowercase version of method name when making request. var methodNameLower = methodName.ToLowerInvariant(); var requestSignature = RpcRequestSignature.Create(methodNameLower, parameters); var previousCulture = System.Globalization.CultureInfo.CurrentCulture; // Switch to a culture that would result in lowercasing 'I' to // U+0131, if not done with invariant culture. System.Globalization.CultureInfo.CurrentCulture = new System.Globalization.CultureInfo("az"); IRpcMethodInfo methodInfo = matcher.GetMatchingMethod(requestSignature); Assert.NotNull(methodInfo); Assert.Equal(methodName, methodInfo.Name); System.Globalization.CultureInfo.CurrentCulture = previousCulture; }
private void Add(RpcPath?path, IRpcMethodInfo methodInfo) { List <IRpcMethodInfo> methods; if (path == null) { methods = this.baseMethods; } else { if (!this.methods.TryGetValue(path, out List <IRpcMethodInfo>?m)) { methods = this.methods[path] = new List <IRpcMethodInfo>(); } else { methods = m !; } } methods.Add(methodInfo); }
public void GetMatchingMethod_ListParam_Match_Snake_Case(string parameterNameCase) { DefaultRequestMatcher matcher = this.GetMatcher(path: typeof(MethodMatcherController).GetTypeInfo().Name); IEnumerable <KeyValuePair <string, RpcParameterType> > parameters = new[] { new KeyValuePair <string, RpcParameterType>(parameterNameCase, RpcParameterType.String) }; string methodName = nameof(MethodMatcherController.SnakeCaseParams); var requestSignature = RpcRequestSignature.Create(methodName, parameters); IRpcMethodInfo methodInfo = matcher.GetMatchingMethod(requestSignature); Assert.NotNull(methodInfo); Assert.Equal(methodName, methodInfo.Name); Assert.Single(methodInfo.Parameters); Assert.False(methodInfo.Parameters[0].IsOptional); Assert.Equal(typeof(string), methodInfo.Parameters[0].RawType); Assert.Equal(RpcParameterType.String, methodInfo.Parameters[0].Type); Assert.True(RpcUtil.NamesMatch(methodInfo.Parameters[0].Name, parameterNameCase)); }
private OpenApiSchema GetBodyParamsSchema(string key, SchemaRepository schemaRepository, IRpcMethodInfo methodInfo) { OpenApiSchema paramsObjectSchema = this.GetOpenApiEmptyObject(); foreach (IRpcParameterInfo parameterInfo in methodInfo.Parameters) { string name = this.namePolicy.ConvertName(parameterInfo.Name); OpenApiSchema schema = this.schemaGenerator.GenerateSchema(parameterInfo.RawType, schemaRepository); paramsObjectSchema.Properties.Add(name, schema); } paramsObjectSchema = schemaRepository.AddDefinition($"{key}", paramsObjectSchema); var requestSchema = this.GetOpenApiEmptyObject(); requestSchema.Properties.Add("id", this.schemaGenerator.GenerateSchema(typeof(string), schemaRepository)); requestSchema.Properties.Add("jsonrpc", this.schemaGenerator.GenerateSchema(typeof(string), schemaRepository)); requestSchema.Properties.Add("method", this.schemaGenerator.GenerateSchema(typeof(string), schemaRepository)); requestSchema.Properties.Add("params", paramsObjectSchema); requestSchema = schemaRepository.AddDefinition($"request_{key}", requestSchema); this.RewriteJrpcAttributesExamples(requestSchema, schemaRepository, this.namePolicy.ConvertName(methodInfo.Name)); return(requestSchema); }
public RpcEndpointBuilder AddMethod(IRpcMethodInfo methodInfo, RpcPath?path = null) { this.Add(path, methodInfo); return(this); }
public UniqueMethod(string uniqueUrl, IRpcMethodInfo info) { this.UniqueUrl = uniqueUrl; this.Info = info; }