private void ApplyFilters(ICurrentApiInformation currentApi, IReadOnlyList <Func <IEndPointMethodConfigurationReadOnly, IEnumerable <Func <RequestExecutionContext, IRequestFilter> > > > filters, EndPointMethodConfiguration configuration) { var filterList = new List <Func <RequestExecutionContext, IRequestFilter> >(); foreach (var filterFunc in currentApi.Filters) { var filter = filterFunc(configuration); if (filter != null) { filterList.Add(filter); } } if (filters != null) { foreach (var filterFunc in filters) { var filter = filterFunc(configuration); if (filter != null) { filterList.AddRange(filter); } } } if (filterList.Count > 0) { configuration.Filters = filterList; } }
private IReadOnlyList <Func <IEndPointMethodConfigurationReadOnly, IEnumerable <Func <RequestExecutionContext, IRequestFilter> > > > GetFilterList( ICurrentApiInformation currentApi, EndPointMethodConfiguration configuration, List <Attribute> classAttributes, List <Attribute> methodAttributes) { var returnList = new List <Func <IEndPointMethodConfigurationReadOnly, IEnumerable <Func <RequestExecutionContext, IRequestFilter> > > >(); foreach (var classAttribute in classAttributes) { if (classAttribute is IRequestFilterAttribute requestFilterAttribute) { var filters = requestFilterAttribute.ProvideFilters(currentApi, configuration); returnList.Add(configReadOnly => filters); } } foreach (var classAttribute in methodAttributes) { if (classAttribute is IRequestFilterAttribute requestFilterAttribute) { var filters = requestFilterAttribute.ProvideFilters(currentApi, configuration); returnList.Add(configReadOnly => filters); } } return(returnList); }
//[Fact] //public async void InvokeTest() //{ // var methodDefinition = CreateSimpleMethodDefinition(out var serializedInstance); // var creator = new DeserializationTypeCreator(); // var serializeType = creator.CreateTypeForMethod(methodDefinition); // var methodInvokerService = new MethodInvokerCreationService(new WrappedResultTypeCreator()); // var invokeDelegate = methodInvokerService.BuildMethodInvoker(methodDefinition, serializeType); // var context = new RequestExecutionContext(null, null, 200) // { // ServiceInstance = new Invoker(), // Parameters = (IRequestParameters)JsonSerializer.Deserialize(serializedInstance, serializeType) // }; // await invokeDelegate(context); //} private static IRequestParameters DeserializeMethodParameters(EndPointMethodConfiguration methodDefinition, string serializedInstance) { var creator = new DeserializationTypeCreator(Array.Empty <ISerializationTypeAttributor>()); var serializeType = creator.CreateTypeForMethod(methodDefinition); return((IRequestParameters)JsonSerializer.Deserialize(serializedInstance, serializeType)); }
private void AssignDefaultValues(EndPointMethodConfiguration configuration, IPathAttribute pathAttribute) { if (pathAttribute != null) { SetStatusAndResponseBodyConfigValues(configuration, pathAttribute.HasResponseBody, pathAttribute.SuccessCodeValue); } else { SetStatusAndResponseBodyConfigValues(configuration, null, null); } }
protected virtual async Task BindParameters <T>(RequestExecutionContext context, EndPointMethodConfiguration configuration, List <RpcParameterInfo> parameters) where T : IRequestParameters { var requestParameters = await _contentSerializationService.DeserializeFromRequest <T>(context); context.Parameters = requestParameters; await BindNonBodyParameters(context, configuration, parameters, requestParameters); }
protected virtual Task BindParameters <T>(RequestExecutionContext context, EndPointMethodConfiguration configuration, IReadOnlyList <RpcParameterInfo> parameters) where T : IRequestParameters, new() { var parameterContext = new T(); context.Parameters = parameterContext; return(BindNonBodyParameters(context, configuration, parameters, parameterContext)); }
private void BindHeaderParameter(RequestExecutionContext context, EndPointMethodConfiguration configuration, IRpcParameterInfo parameter, IRequestParameters parameters) { if (context.HttpContext.Request.Headers.TryGetValue(parameter.BindName, out var value)) { var boundValue = _stringValueModelBinder.ConvertString(parameter, value); parameters[parameter.Position] = boundValue; } else if (parameter.HasDefaultValue) { parameters[parameter.Position] = parameter.DefaultValue; } }
protected virtual async Task BindParameters <T, TContext>(RequestExecutionContext context, EndPointMethodConfiguration configuration, List <RpcParameterInfo> parameters, int parameterPosition) where TContext : IRequestParameters, new() { var requestParameters = new TContext(); context.Parameters = requestParameters; var bodyParameter = await _contentSerializationService.DeserializeFromRequest <T>(context); requestParameters[parameterPosition] = bodyParameter; await BindNonBodyParameters(context, configuration, parameters, requestParameters); }
protected virtual void ApplyAuthorizations(ICurrentApiInformation currentApi, IReadOnlyList <Func <IEndPointMethodConfigurationReadOnly, IEnumerable <IEndPointMethodAuthorization> > > authorizationFuncList, EndPointMethodConfiguration configuration, List <Attribute> classAttributes, List <Attribute> methodAttributes) { // anything marked as anonymous we want to allow if (classAttributes.Any(a => a is AllowAnonymousAttribute) || methodAttributes.Any(a => a is AllowAnonymousAttribute)) { return; } var authorizationList = new List <IEndPointMethodAuthorization>(); foreach (var authorizationFunc in currentApi.Authorizations) { var authorizations = authorizationFunc(configuration); if (authorizations != null) { authorizationList.AddRange(authorizations); } } if (authorizationFuncList != null) { foreach (var authorizationFunc in authorizationFuncList) { var authorizations = authorizationFunc(configuration); if (authorizations != null) { authorizationList.AddRange(authorizations); } } } ProcessAuthorizeAttributes(classAttributes, authorizationList); ProcessAuthorizeAttributes(methodAttributes, authorizationList); if (authorizationList.Count > 0) { configuration.Authorizations = authorizationList; } }
/// <inheritdoc /> public StateBasedEndPointMethodHandler(EndPointMethodConfiguration configuration, EndPointServices services) : base(configuration, services) { _startingState = RequestState.ExecuteTask; if (configuration.Authorizations != null && configuration.Authorizations.Count > 0) { _startingState = RequestState.CheckAuth; } else if (configuration.Filters != null && configuration.Filters.Count > 0) { _startingState = RequestState.CreateFilters; } else if (configuration.Parameters.Count > 0) { _startingState = RequestState.BindParameters; } }
private IEnumerable <RpcParameterInfo> AddInstancePropertyBindingParameters(EndPointMethodConfiguration configuration, Type type) { var position = 0; configuration.Parameters.ForEach(p => { if (p.Position > position) { position = p.Position + 1; } }); foreach (var propertyInfo in type.GetProperties(BindingFlags.Instance | BindingFlags.Public)) { if (propertyInfo.PropertyType == typeof(RequestExecutionContext)) { yield return(new RpcParameterInfo { BindingType = EndPointBindingType.InstanceProperty, Name = propertyInfo.Name, HasDefaultValue = false, ParamType = propertyInfo.PropertyType, ParameterSource = EndPointMethodParameterSource.RequestExecutionContext, Position = position++ }); } else if (propertyInfo.PropertyType == typeof(HttpContext)) { yield return(new RpcParameterInfo { BindingType = EndPointBindingType.InstanceProperty, Name = propertyInfo.Name, ParamType = propertyInfo.PropertyType, ParameterSource = EndPointMethodParameterSource.HttpContext, Position = position++ }); } else { } } }
private static EndPointMethodConfiguration CreateEndPointMethodConfiguration(string path) { var routeInfo = new RpcRouteInformation { HasBody = false, Method = HttpMethods.Get, RouteBasePath = path, RouteTemplate = path, Tokens = Array.Empty <IRpcRouteToken>() }; var invokeFunc = new MethodInvokeInformation { MethodInvokeDelegate = context => null }; var configuration = new EndPointMethodConfiguration(routeInfo, context => null, invokeFunc, typeof(void)); return(configuration); }
private static EndPointMethodConfiguration CreateSimpleMethodDefinition(out string serializedInstance) { var invokeInfo = new MethodInvokeInformation { MethodToInvoke = typeof(Invoker).GetMethod("InvokeMethod") }; var methodDefinition = new EndPointMethodConfiguration(new RpcRouteInformation(), null, invokeInfo, typeof(ResultHolder)); methodDefinition.Parameters.Add(new RpcParameterInfo { Name = "intValue", ParamType = typeof(int), Position = 0 }); methodDefinition.Parameters.Add(new RpcParameterInfo { Name = "stringValue", ParamType = typeof(string), Position = 1 }); methodDefinition.Parameters.Add(new RpcParameterInfo { Name = "nullableBoolValue", ParamType = typeof(bool?), Position = 1 }); serializedInstance = "{\"intValue\": 5, \"stringValue\":\"blah\", \"nullableBoolValue\": true}"; return(methodDefinition); }
/// <summary> /// Bind non body parameters (url, query string, etc) /// </summary> /// <typeparam name="T"></typeparam> /// <param name="context"></param> /// <param name="configuration"></param> /// <param name="parameters"></param> /// <param name="parameterContext"></param> /// <returns></returns> protected virtual Task BindNonBodyParameters <T>(RequestExecutionContext context, EndPointMethodConfiguration configuration, IReadOnlyList <RpcParameterInfo> parameters, T parameterContext) where T : IRequestParameters { var pathSpan = context.HttpContext.Request.Path.Value.AsSpan(); var currentIndex = configuration.RouteInformation.RouteBasePath.Length; for (var i = 0; i < parameters.Count; i++) { var parameter = parameters[i]; if (parameter.BindAction != null) { parameter.BindAction(context, configuration, parameter, parameterContext); } else if (parameter.ParameterSource == EndPointMethodParameterSource.PathParameter) { UrlParameterBinder.BindUrlParameter(context, configuration, parameter, parameterContext, ref currentIndex, pathSpan); } } return(Task.CompletedTask); }
/// <summary> /// Create endpoints for a delegate /// </summary> /// <param name="currentApi"></param> /// <param name="instanceConfiguration"></param> /// <param name="func"></param> /// <returns></returns> protected virtual IEnumerable <EndPointMethodConfiguration> CreateEndPointMethodConfigurationForDelegate(ICurrentApiInformation currentApi, BaseDelegateInstanceConfiguration instanceConfiguration, Delegate func) { var fullPath = instanceConfiguration.Path; var funcMethod = func.Method; var routeList = GenerateRouteInformationList(fullPath, instanceConfiguration.Method, GetDefaultRequestBody(instanceConfiguration.Method, instanceConfiguration.HasRequestBody), currentApi, typeof(object), "", funcMethod, new List <Attribute>()); foreach (var routeInformation in routeList) { var configuration = new EndPointMethodConfiguration(routeInformation, context => null, new MethodInvokeInformation { DelegateToInvoke = func }, funcMethod.ReturnType); var parameters = GenerateMethodParameters(null, funcMethod, routeInformation); configuration.Parameters.AddRange(parameters); configuration.RawContentType = instanceConfiguration.RawContentType; SetStatusAndResponseBodyConfigValues(configuration, instanceConfiguration.HasResponseBody, instanceConfiguration.SuccessStatusCode); if (string.IsNullOrEmpty(configuration.RawContentType)) { var returnType = funcMethod.ReturnType; if (returnType.IsConstructedGenericType && (returnType.GetGenericTypeDefinition() == typeof(Task <>) || returnType.GetGenericTypeDefinition() == typeof(ValueTask <>))) { returnType = returnType.GenericTypeArguments[0]; } if (_exposeConfigurations.TypeWrapSelector(returnType)) { configuration.WrappedType = _wrappedResultTypeCreator.GetTypeWrapper(returnType); } } if (currentApi.Headers != ImmutableLinkedList <IResponseHeader> .Empty || instanceConfiguration.Headers != ImmutableLinkedList <IResponseHeader> .Empty) { var responseHeaders = new List <IResponseHeader>(); responseHeaders.AddRange(currentApi.Headers); responseHeaders.AddRange(instanceConfiguration.Headers); configuration.ResponseHeaders = responseHeaders; } ApplyAuthorizations(currentApi, null, configuration, EmptyList, EmptyList); ApplyFilters(currentApi, GetFilterList(currentApi, configuration, EmptyList, EmptyList), configuration); if (_supportCompression) { configuration.SupportsCompression = _compressionSelectorService.ShouldCompressResult(configuration); } yield return(configuration); } }
public virtual void BindHttpCancellationTokenParameter(RequestExecutionContext context, EndPointMethodConfiguration endPointMethodConfiguration, IRpcParameterInfo parameter, IRequestParameters parameterContext) { parameterContext[parameter.Position] = context.HttpContext.RequestAborted; }
/// <inheritdoc /> public void BindUrlParameter(RequestExecutionContext context, EndPointMethodConfiguration configuration, IRpcParameterInfo parameter, IRequestParameters parameterContext, ref int currentIndex, in ReadOnlySpan <char> pathSpan)
private IEndPointMethodHandler CreateEndPointMethodHandler(ICurrentApiInformation currentApi, EndPointMethodConfiguration configuration) { var returnType = configuration.WrappedType ?? configuration.ReturnType; Type closedType; if (returnType.IsConstructedGenericType && (returnType.GetGenericTypeDefinition() == typeof(Task <>) || returnType.GetGenericTypeDefinition() == typeof(ValueTask <>))) { returnType = returnType.GenericTypeArguments[0]; } else if (returnType == typeof(Task) || returnType == typeof(ValueTask) || returnType == typeof(void)) { // set it to object and it will get wrapped later returnType = typeof(object); } if (configuration.Authorizations == null || configuration.Authorizations.Count == 0) { if (configuration.Parameters.Count == 0 && (configuration.Filters == null || configuration.Filters.Count == 0)) { closedType = typeof(NoParamsEndPointMethodHandler <>).MakeGenericType(returnType); return((IEndPointMethodHandler)Activator.CreateInstance(closedType, configuration, _services)); } } closedType = typeof(StateBasedEndPointMethodHandler <>).MakeGenericType(returnType); return((IEndPointMethodHandler)Activator.CreateInstance(closedType, configuration, _services)); }
private IEnumerable <EndPointMethodConfiguration> CreateEndPointMethodConfiguration( ICurrentApiInformation currentApi, Type type, ServiceActivationMethod serviceActivationMethod, Func <RequestExecutionContext, object> activationFunc, List <Attribute> classAttributes, string name, List <IEndPointMethodAuthorization> authorizations, string obsoleteMessage, MethodInfo methodInfo, List <Attribute> methodAttributes, IPathAttribute pathAttribute) { string methodPath; string methodVerb; bool methodHasBody; (methodPath, methodVerb, methodHasBody) = GenerateMethodPath(currentApi, type, name, methodInfo, classAttributes, methodAttributes, pathAttribute); if (activationFunc == null) { activationFunc = GenerateActivation(currentApi, type, classAttributes, name, methodInfo, methodAttributes); } foreach (var routeInformation in GenerateRouteInformationList(methodPath, methodVerb, methodHasBody, currentApi, type, name, methodInfo, methodAttributes)) { var configuration = new EndPointMethodConfiguration(routeInformation, activationFunc, new MethodInvokeInformation { MethodToInvoke = methodInfo }, methodInfo.ReturnType); AssignDefaultValues(configuration, pathAttribute); var methodParameters = GenerateMethodParameters(type, methodInfo, routeInformation); configuration.Parameters.AddRange(methodParameters); configuration.Parameters.AddRange(AddInstancePropertyBindingParameters(configuration, type)); var rawAttribute = (IRawContentAttribute)methodAttributes.FirstOrDefault(a => a is IRawContentAttribute); if (rawAttribute != null) { configuration.RawContentType = rawAttribute.ContentType; configuration.RawContentEncoding = rawAttribute.ContentEncoding; } else if (string.IsNullOrEmpty(configuration.RawContentType)) { var returnType = methodInfo.ReturnType; if (returnType.IsConstructedGenericType && (returnType.GetGenericTypeDefinition() == typeof(Task <>) || returnType.GetGenericTypeDefinition() == typeof(ValueTask <>))) { returnType = returnType.GenericTypeArguments[0]; } if (_exposeConfigurations.TypeWrapSelector(returnType)) { configuration.WrappedType = _wrappedResultTypeCreator.GetTypeWrapper(returnType); } } var headerAttributes = classAttributes.Where(a => a is ResponseHeaderAttribute).ToList(); headerAttributes.AddRange(methodAttributes.Where(a => a is ResponseHeaderAttribute)); if (headerAttributes.Count > 0 || currentApi.Headers != ImmutableLinkedList <IResponseHeader> .Empty) { var headers = new List <IResponseHeader>(); headers.AddRange(currentApi.Headers); foreach (ResponseHeaderAttribute headerAttribute in headerAttributes) { headers.Add(new ResponseHeader.ResponseHeader(headerAttribute.Name, headerAttribute.Value)); } configuration.ResponseHeaders = headers; } Func <IEndPointMethodConfigurationReadOnly, IEnumerable <IEndPointMethodAuthorization> >[] authorizationFunc = null; if (authorizations != null) { authorizationFunc = new Func <IEndPointMethodConfigurationReadOnly, IEnumerable <IEndPointMethodAuthorization> >[] { config => authorizations }; } ApplyAuthorizations(currentApi, authorizationFunc, configuration, classAttributes, methodAttributes); ApplyFilters(currentApi, GetFilterList(currentApi, configuration, classAttributes, methodAttributes), configuration); if (_supportCompression) { configuration.SupportsCompression = _compressionSelectorService.ShouldCompressResult(configuration); } var returnTypeAttribute = (ReturnsTypeAttribute)methodAttributes.FirstOrDefault(a => a is ReturnsTypeAttribute); configuration.DocumentationReturnType = returnTypeAttribute?.ReturnType; yield return(configuration); } }
protected virtual void BindQueryStringParameter(RequestExecutionContext context, EndPointMethodConfiguration configuration, IRpcParameterInfo parameter, IRequestParameters parameters) { if (context.HttpContext.Request.Query.TryGetValue(parameter.BindName, out var value)) { var boundValue = _stringValueModelBinder.ConvertString(parameter, value); context.Parameters[parameter.Position] = boundValue; } else if (parameter.HasDefaultValue) { context.Parameters[parameter.Position] = parameter.DefaultValue; } }
protected virtual void BindNewData <TValue>(RequestExecutionContext context, EndPointMethodConfiguration configuration, IRpcParameterInfo parameter, IRequestParameters parameterContext) where TValue : new() { parameterContext[parameter.Position] = new TValue(); }
public virtual void BindHttpResponseParameter(RequestExecutionContext context, EndPointMethodConfiguration endPointMethodConfiguration, IRpcParameterInfo parameter, IRequestParameters parameterContext) { parameterContext[parameter.Position] = context.HttpContext.Response; }
/// <summary> /// Default constructor /// </summary> /// <param name="configuration"></param> /// <param name="services"></param> protected BaseContentEndPointMethodHandler(EndPointMethodConfiguration configuration, EndPointServices services) { Configuration = configuration; Services = services; HttpMethod = configuration.RouteInformation.Method; }
private void SetStatusAndResponseBodyConfigValues(EndPointMethodConfiguration configuration, bool?hasResponseBody, int?successStatusCode) { var finalResponseBody = hasResponseBody; var finalStatusCode = successStatusCode; if (configuration.RouteInformation.Method == HttpMethods.Get) { configuration.HasResponseBody = finalResponseBody.GetValueOrDefault(_defaultMethodConfiguration.GetHasResponseBody); configuration.SuccessStatusCode = finalStatusCode.GetValueOrDefault(_defaultMethodConfiguration.GetSuccessStatusCode); } else if (configuration.RouteInformation.Method == HttpMethods.Head) { configuration.HasResponseBody = finalResponseBody.GetValueOrDefault(_defaultMethodConfiguration.HeadHasResponseBody); configuration.SuccessStatusCode = finalStatusCode.GetValueOrDefault(_defaultMethodConfiguration.HeadSuccessStatusCode); } else if (configuration.RouteInformation.Method == HttpMethods.Post) { configuration.HasResponseBody = finalResponseBody.GetValueOrDefault(_defaultMethodConfiguration.PostHasResponseBody); configuration.SuccessStatusCode = finalStatusCode.GetValueOrDefault(_defaultMethodConfiguration.PostSuccessStatusCode); } else if (configuration.RouteInformation.Method == HttpMethods.Put) { configuration.HasResponseBody = finalResponseBody.GetValueOrDefault(_defaultMethodConfiguration.PutHasResponseBody); configuration.SuccessStatusCode = finalStatusCode.GetValueOrDefault(_defaultMethodConfiguration.PutSuccessStatusCode); } else if (configuration.RouteInformation.Method == HttpMethods.Patch) { configuration.HasResponseBody = finalResponseBody.GetValueOrDefault(_defaultMethodConfiguration.PatchHasResponseBody); configuration.SuccessStatusCode = finalStatusCode.GetValueOrDefault(_defaultMethodConfiguration.PatchSuccessStatusCode); } else if (configuration.RouteInformation.Method == HttpMethods.Delete) { configuration.HasResponseBody = finalResponseBody.GetValueOrDefault(_defaultMethodConfiguration.DeleteHasResponseBody); configuration.SuccessStatusCode = finalStatusCode.GetValueOrDefault(_defaultMethodConfiguration.DeleteSuccessStatusCode); } else if (configuration.RouteInformation.Method == HttpMethods.Options) { configuration.HasResponseBody = finalResponseBody.GetValueOrDefault(_defaultMethodConfiguration.OptionsHasResponseBody); configuration.SuccessStatusCode = finalStatusCode.GetValueOrDefault(_defaultMethodConfiguration.OptionsSuccessStatusCode); } else { configuration.HasResponseBody = finalResponseBody.GetValueOrDefault(_defaultMethodConfiguration.UnknownMethodResponseBody(configuration.RouteInformation.Method)); configuration.SuccessStatusCode = finalStatusCode.GetValueOrDefault(_defaultMethodConfiguration.UnknownMethodStatusCode(configuration.RouteInformation.Method)); } }
/// <summary> /// Default constructor /// </summary> /// <param name="configuration"></param> /// <param name="services"></param> public NoParamsEndPointMethodHandler(EndPointMethodConfiguration configuration, EndPointServices services) : base(configuration, services) { }
public virtual void BindRequestServicesParameter(RequestExecutionContext context, EndPointMethodConfiguration endPointMethodConfiguration, IRpcParameterInfo parameter, IRequestParameters parameterContext) { parameterContext[parameter.Position] = context.HttpContext.RequestServices.GetService(parameter.ParamType); }