public async Task Invoke(HttpContext context)
        {
            var uri           = GeRequestUri(context);
            var resultBuilder = new ProxyResultBuilder(uri);

            var matchedRule = _options.ProxyRules.FirstOrDefault(r => r.Matcher(uri));

            if (matchedRule == null)
            {
                await _next(context);

                _options.Reporter.Invoke(resultBuilder.NotProxied(context.Response.StatusCode));
                return;
            }

            if (matchedRule.RequiresAuthentication && !UserIsAuthenticated(context))
            {
                AuthenticateResult authResult = AuthenticateResult.Fail("Authentication failure");
                foreach (var authScheme in matchedRule.AuthenticationSchemes)
                {
                    authResult = await context.AuthenticateAsync(authScheme);

                    if (authResult.Succeeded)
                    {
                        context.User = authResult.Principal;
                        break;
                    }
                }

                if (!authResult.Succeeded)
                {
                    context.Response.StatusCode = StatusCodes.Status401Unauthorized;
                    _options.Reporter.Invoke(resultBuilder.NotAuthenticated());
                    return;
                }
            }

            var proxyRequest = new HttpRequestMessage(new HttpMethod(context.Request.Method), uri);

            SetProxyRequestBody(proxyRequest, context);
            SetProxyRequestHeaders(proxyRequest, context);

            matchedRule.Modifier(proxyRequest, context.User);

            proxyRequest.Headers.Host = !proxyRequest.RequestUri.IsDefaultPort
                ? $"{proxyRequest.RequestUri.Host}:{proxyRequest.RequestUri.Port}"
                : proxyRequest.RequestUri.Host;

            try {
                await ProxyTheRequest(context, proxyRequest, matchedRule);
            }
            catch (HttpRequestException) {
                context.Response.StatusCode = StatusCodes.Status503ServiceUnavailable;
            }
            _options.Reporter.Invoke(resultBuilder.Proxied(proxyRequest.RequestUri, context.Response.StatusCode));
        }
Example #2
0
        public async Task Invoke(HttpContext context)
        {
            var uri           = GeRequestUri(context);
            var resultBuilder = new ProxyResultBuilder(uri);

            var matchedRule = _options.ProxyRules.FirstOrDefault(r => r.Matcher.Invoke(uri));

            if (matchedRule == null)
            {
                await _next(context);

                _options.Reporter.Invoke(resultBuilder.NotProxied(context.Response.StatusCode));
                return;
            }

            if (matchedRule.RequiresAuthentication && !UserIsAuthenticated(context))
            {
                context.Response.StatusCode = StatusCodes.Status401Unauthorized;
                _options.Reporter.Invoke(resultBuilder.NotAuthenticated());
                return;
            }

            var proxyRequest = new HttpRequestMessage(new HttpMethod(context.Request.Method), uri);

            SetProxyRequestBody(proxyRequest, context);
            SetProxyRequestHeaders(proxyRequest, context);

            matchedRule.Modifier.Invoke(proxyRequest, context.User);

            proxyRequest.Headers.Host = proxyRequest.RequestUri.Host;

            if (proxyRequest.Content != null)
            {
                await proxyRequest.Content.LoadIntoBufferAsync();
            }

            await resultBuilder.HttpRequest(proxyRequest);

            try {
                await ProxyTheRequest(context, proxyRequest, matchedRule, resultBuilder);
            }
            catch (HttpRequestException) {
                context.Response.StatusCode = StatusCodes.Status503ServiceUnavailable;
            }

            _options.Reporter.Invoke(resultBuilder.Proxied(proxyRequest.RequestUri, context.Response.StatusCode));
        }
        public async Task Invoke(HttpContext context)
        {
            var uri           = GeRequestUri(context);
            var resultBuilder = new ProxyResultBuilder(uri);

            var matchedRule = _options.ProxyRules.FirstOrDefault(r => r.Matcher.Invoke(uri));

            if (matchedRule == null)
            {
                await _next(context);

                _options.Reporter?.Invoke(resultBuilder.NotProxied(context.Response.StatusCode));
                return;
            }

            if (matchedRule.RequiresAuthentication && !UserIsAuthenticated(context))
            {
                context.Response.StatusCode = StatusCodes.Status401Unauthorized;
                _options.Reporter?.Invoke(resultBuilder.NotAuthenticated());
                return;
            }

            var proxyRequest = new HttpRequestMessage(new HttpMethod(context.Request.Method), uri);
            var client       = matchedRule.GetClient != null?matchedRule.GetClient(context.Request, context.User) : _httpClient;

            SetProxyRequestBody(proxyRequest, context);
            SetProxyRequestHeaders(proxyRequest, context);

            matchedRule.Modifier.Invoke(proxyRequest, context.User);

            proxyRequest.Headers.Host = !proxyRequest.RequestUri.IsDefaultPort
                ? $"{proxyRequest.RequestUri.Host}:{proxyRequest.RequestUri.Port}"
                : proxyRequest.RequestUri.Host;

            try
            {
                await ProxyTheRequest(client, context, proxyRequest, matchedRule, matchedRule.HeadersToRemove);
            }
            catch (HttpRequestException err)
            {
                matchedRule.ErrorHandler?.Invoke(err);
                context.Response.StatusCode = StatusCodes.Status503ServiceUnavailable;
            }
            _options.Reporter?.Invoke(resultBuilder.Proxied(proxyRequest.RequestUri, context.Response.StatusCode));
        }
Example #4
0
        private async Task ProxyTheRequest(HttpContext context, HttpRequestMessage proxyRequest, ProxyRule proxyRule, ProxyResultBuilder resultBuilder)
        {
            using (var responseMessage = await _httpClient.SendAsync(proxyRequest,
                                                                     HttpCompletionOption.ResponseHeadersRead,
                                                                     context.RequestAborted)) {
                if (proxyRule.PreProcessResponse || proxyRule.ResponseModifier == null)
                {
                    context.Response.StatusCode  = (int)responseMessage.StatusCode;
                    context.Response.ContentType = responseMessage.Content?.Headers.ContentType?.MediaType;
                    foreach (var header in responseMessage.Headers)
                    {
                        context.Response.Headers[header.Key] = header.Value.ToArray();
                    }
                    // SendAsync removes chunking from the response.
                    // This removes the header so it doesn't expect a chunked response.
                    context.Response.Headers.Remove("transfer-encoding");

                    if (responseMessage.Content != null)
                    {
                        foreach (var contentHeader in responseMessage.Content.Headers)
                        {
                            context.Response.Headers[contentHeader.Key] = contentHeader.Value.ToArray();
                        }

                        //this was throwing an exception attempting to add body on a 204 response. is there another way to check?
                        if (responseMessage.StatusCode != HttpStatusCode.NoContent)
                        {
                            await responseMessage.Content.LoadIntoBufferAsync();

                            await responseMessage.Content.CopyToAsync(context.Response.Body);
                        }
                    }
                }

                if (proxyRule.ResponseModifier != null)
                {
                    await proxyRule.ResponseModifier.Invoke(responseMessage, context);
                }

                await resultBuilder.HttpResponse(responseMessage);
            }
        }