예제 #1
0
        private async Task WriteToAspNetCoreResponseBodyAsync(HttpContext context, MiddlerContext middlerContext)
        {
            //if (originalBody == null)
            //    return;


            //var tempStream = context.Response.Body;
            //context.Response.Body = originalBody;

            foreach (var(key, value) in middlerContext.MiddlerResponseContext.Headers)
            {
                context.Response.Headers[key] = value;
            }

            if (middlerContext.Response.StatusCode != 0)
            {
                context.Response.StatusCode = middlerContext.Response.StatusCode;
            }


            context.Response.Headers["Content-Type"] = "application/json";
            context.Response.Headers.ContentLength   = null;
            if (context.Response.Body.CanWrite)
            {
                middlerContext.MiddlerResponseContext.Body.Seek(0, SeekOrigin.Begin);
                await middlerContext.MiddlerResponseContext.Body.CopyToAsync(context.Response.Body, 131072, context.RequestAborted).ConfigureAwait(false);

                await context.Response.Body.FlushAsync(context.RequestAborted).ConfigureAwait(false);
            }


            await middlerContext.MiddlerResponseContext.Body.DisposeAsync().ConfigureAwait(false);
        }
예제 #2
0
        private async Task ExecuteResponseAction(IMiddlerAction middlerAction, MiddlerContext middlerContext)
        {
            var method = middlerAction.GetType().GetMethod("ExecuteResponseAsync") ?? middlerAction.GetType().GetMethod("ExecuteResponse");

            if (method == null)
            {
                return;
            }

            var man = new Dictionary <Type, object>
            {
            };

            var parameters = BuildExecuteMethodParameters(method, middlerContext, man);

            if (typeof(Task).IsAssignableFrom(method.ReturnType))
            {
                var t = (Task)method.Invoke(middlerAction, parameters);
                await t.ConfigureAwait(false);
            }
            else
            {
                method.Invoke(middlerAction, parameters);
            }
        }
예제 #3
0
        private object[] BuildExecuteMethodParameters(MethodInfo methodInfo, MiddlerContext middlerContext, Dictionary <Type, object> manualCreateParameters)
        {
            return(methodInfo.GetParameters().Select(p =>
            {
                if (manualCreateParameters.TryGetValue(p.ParameterType, out var manualCreated))
                {
                    return manualCreated;
                }

                if (p.ParameterType == typeof(IMiddlerContext))
                {
                    return middlerContext;
                }


                if (p.ParameterType == typeof(IActionHelper))
                {
                    return new ActionHelper(middlerContext.Request);
                }

                return middlerContext.RequestServices.GetRequiredService(p.ParameterType);
            }).ToArray());
        }
예제 #4
0
        public async Task InvokeAsync(HttpContext httpContext, IMiddlerOptions middlerOptions, InternalHelper intHelper)
        {
            var sw = new Stopwatch();

            sw.Start();
            EnsureLoggers(httpContext);
            //Stream originalBody = null;

            var middlerMap = httpContext.RequestServices.GetRequiredService <IMiddlerMap>();


            var endpoints = middlerMap.GetFlatList(httpContext.RequestServices);

            var executedActions = new Stack <IMiddlerAction>();

            var middlerContext = new MiddlerContext(httpContext, middlerOptions);

            //var first = true;
            try
            {
                bool terminating;
                do
                {
                    var matchingEndpoint = FindMatchingEndpoint(middlerOptions, endpoints, middlerContext);

                    if (matchingEndpoint == null)
                    {
                        //await _next(httpContext).ConfigureAwait(false);
                        break;
                    }

                    if (matchingEndpoint.AccessMode == AccessMode.Deny)
                    {
                        await httpContext.Forbid().ConfigureAwait(false);

                        return;
                    }

                    //middlerContext.Features.Set(matchingEndpoint);

                    endpoints = matchingEndpoint.RemainingEndpointInfos;

                    //var interMediateStreamNeeded = matchingEndpoint.MiddlerRule.Actions.Any(a => !a.WriteStreamDirect);
                    //if (interMediateStreamNeeded)
                    //{
                    //    originalBody ??= httpContext.Response.Body;
                    //    httpContext.Response.Body = new AutoStream(opts =>
                    //        opts
                    //            .WithMemoryThreshold(middlerOptions.AutoStreamDefaultMemoryThreshold)
                    //            .WithFilePrefix("middler"), middlerContext.Request.RequestAborted);

                    //}



                    terminating = false;
                    foreach (var endpointAction in matchingEndpoint.MiddlerRule.Actions)
                    {
                        if (!endpointAction.Enabled)
                        {
                            continue;
                        }
                        //if (!first)
                        //{
                        //    middlerContext.PrepareNext();
                        //}
                        var action = intHelper.BuildConcreteActionInstance(endpointAction);
                        if (action != null)
                        {
                            await ExecuteRequestAction(action, middlerContext);

                            executedActions.Push(action);
                            terminating = action.Terminating;
                            //first = false;
                        }

                        if (terminating)
                        {
                            break;
                        }
                    }
                } while (!terminating);


                if (executedActions.Any())
                {
                    while (executedActions.TryPop(out var executedAction))
                    {
                        await ExecuteResponseAction(executedAction, middlerContext);
                    }

                    //httpContext.Response.Body = middlerContext.MiddlerResponseContext.Body;

                    await WriteToAspNetCoreResponseBodyAsync(httpContext, middlerContext).ConfigureAwait(false);
                }
                else
                {
                    await _next(httpContext);
                }
            }
            catch (Exception ex)
            {
                Logger.LogError(ex, ex.Message);
                throw;
            }
        }
예제 #5
0
        private MiddlerRuleMatch CheckMatch(IMiddlerOptions middlerOptions, MiddlerRule rule, MiddlerContext middlerContext)
        {
            var allowedHttpMethods = (rule.HttpMethods?.IgnoreNullOrWhiteSpace().Any() == true ? rule.HttpMethods.IgnoreNullOrWhiteSpace() : middlerOptions.DefaultHttpMethods).ToList();

            if (allowedHttpMethods.Any() && !allowedHttpMethods.Contains(middlerContext.Request.HttpMethod, StringComparer.OrdinalIgnoreCase))
            {
                return(null);
            }

            //var uri = new Uri(context.Request.GetEncodedUrl());

            var allowedSchemes = (rule.Scheme?.IgnoreNullOrWhiteSpace().Any() == true ? rule.Scheme.IgnoreNullOrWhiteSpace() : middlerOptions.DefaultScheme).ToList();

            if (allowedSchemes.Any() && !allowedSchemes.Any(scheme => Wildcard.Match(middlerContext.MiddlerRequestContext.Uri.Scheme, scheme)))
            {
                return(null);
            }

            if (!Wildcard.Match($"{middlerContext.MiddlerRequestContext.Uri.Host}:{middlerContext.MiddlerRequestContext.Uri.Port}", rule.Hostname ?? "*"))
            {
                return(null);
            }

            if (String.IsNullOrWhiteSpace(rule.Path))
            {
                rule.Path = "{**path}";
            }

            var parsedTemplate = TemplateParser.Parse(rule.Path);

            var defaults = parsedTemplate.Parameters.Where(p => p.DefaultValue != null)
                           .Aggregate(new RouteValueDictionary(), (current, next) =>
            {
                current.Add(next.Name, next.DefaultValue);
                return(current);
            });

            var matcher = new TemplateMatcher(parsedTemplate, defaults);
            var rd      = middlerContext.MiddlerRequestContext.GetRouteData();
            var router  = rd.Routers.FirstOrDefault() ?? new RouteCollection();

            if (matcher.TryMatch(middlerContext.MiddlerRequestContext.Uri.AbsolutePath, rd.Values))
            {
                var constraints = GetConstraints(middlerContext.RequestServices.GetRequiredService <IInlineConstraintResolver>(), parsedTemplate, null);
                if (MiddlerRouteConstraintMatcher.Match(constraints, rd.Values, router, RouteDirection.IncomingRequest, ConstraintLogger))
                {
                    middlerContext.SetRouteData(constraints);

                    return(new MiddlerRuleMatch
                    {
                        MiddlerRule = rule,
                        AccessMode = rule.AccessAllowed(middlerContext.Request) ?? middlerOptions.DefaultAccessMode
                    });
                }
            }

            return(null);
        }
예제 #6
0
        private MiddlerRuleMatch FindMatchingEndpoint(IMiddlerOptions middlerOptions, List <MiddlerRule> rule, MiddlerContext middlerContext)
        {
            for (int i = 0; i < rule.Count; i++)
            {
                var match = CheckMatch(middlerOptions, rule[i], middlerContext);
                if (match != null)
                {
                    if (match.AccessMode != AccessMode.Ignore)
                    {
                        match.RemainingEndpointInfos = rule.Skip(i + 1).ToList();
                        return(match);
                    }
                }
            }

            return(null);
        }