public override void Apply(RequestParametersTransformContext context)
 {
     if (context is null)
     {
         throw new ArgumentNullException(nameof(context));
     }
     context.Path = string.Empty;
 }
        public override void Apply(RequestParametersTransformContext context)
        {
            if (context == null)
            {
                throw new System.ArgumentNullException(nameof(context));
            }

            context.Query.Collection.Remove(_key);
        }
Exemple #3
0
        protected override string GetValue(RequestParametersTransformContext context)
        {
            var routeValues = context.HttpContext.Request.RouteValues;

            if (!routeValues.TryGetValue(RouteValueKey, out var value))
            {
                return(null);
            }

            return(value.ToString());
        }
Exemple #4
0
        private HttpRequestMessage CreateRequestMessage(HttpContext context, string destinationAddress, bool isUpgradeRequest, IReadOnlyList <RequestParametersTransform> transforms)
        {
            // "http://a".Length = 8
            if (destinationAddress == null || destinationAddress.Length < 8)
            {
                throw new ArgumentException(nameof(destinationAddress));
            }

            // Default to HTTP/1.1 for proxying upgradeable requests. This is already the default as of .NET Core 3.1
            // Otherwise request HTTP/2 and let HttpClient fallback to HTTP/1.1 if it cannot establish HTTP/2 with the target.
            // This is done without extra round-trips thanks to ALPN. We can detect a downgrade after calling HttpClient.SendAsync
            // (see Step 3 below). TBD how this will change when HTTP/3 is supported.
            var httpVersion = isUpgradeRequest ? ProtocolHelper.Http11Version : ProtocolHelper.Http2Version;

            // TODO Perf: We could probably avoid splitting this and just append the final path and query
            UriHelper.FromAbsolute(destinationAddress, out var destinationScheme, out var destinationHost, out var destinationPathBase, out _, out _); // Query and Fragment are not supported here.

            var request = context.Request;

            if (transforms.Count == 0)
            {
                var url = UriHelper.BuildAbsolute(destinationScheme, destinationHost, destinationPathBase, request.Path, request.QueryString);
                Log.Proxying(_logger, url);
                var uri = new Uri(url, UriKind.Absolute);
                return(new HttpRequestMessage(HttpUtilities.GetHttpMethod(context.Request.Method), uri)
                {
                    Version = httpVersion
                });
            }

            var transformContext = new RequestParametersTransformContext()
            {
                HttpContext = context,
                Version     = httpVersion,
                Method      = request.Method,
                Path        = request.Path,
                Query       = new QueryTransformContext(request),
            };

            foreach (var transform in transforms)
            {
                transform.Apply(transformContext);
            }

            var targetUrl = UriHelper.BuildAbsolute(destinationScheme, destinationHost, destinationPathBase, transformContext.Path, transformContext.Query.QueryString);

            Log.Proxying(_logger, targetUrl);
            var targetUri = new Uri(targetUrl, UriKind.Absolute);

            return(new HttpRequestMessage(HttpUtilities.GetHttpMethod(transformContext.Method), targetUri)
            {
                Version = transformContext.Version
            });
        }
Exemple #5
0
        public override void Apply(RequestParametersTransformContext context)
        {
            if (context is null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            var parametersToRemove = context.Query.Collection.Keys
                                     .Where(x => x.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)).ToList();

            parametersToRemove.ForEach(x => context.Query.Collection.Remove(x));
        }
Exemple #6
0
        private HttpRequestMessage CreateRequestMessage(HttpContext context,
                                                        string destinationAddress,
                                                        Version httpVersion,
                                                        IReadOnlyList <RequestParametersTransform> transforms)
        {
            // "http://a".Length = 8
            if (destinationAddress == null || destinationAddress.Length < 8)
            {
                throw new ArgumentException(nameof(destinationAddress));
            }

            // TODO Perf: We could probably avoid splitting this and just append the final path and query
            UriHelper.FromAbsolute(destinationAddress, out var destinationScheme, out var destinationHost, out var destinationPathBase, out _, out _); // Query and Fragment are not supported here.

            var request = context.Request;

            if (transforms.Count == 0)
            {
                var url = UriHelper.BuildAbsolute(destinationScheme, destinationHost, destinationPathBase, request.Path, request.QueryString);
                Log.Proxying(_logger, url);
                var uri = new Uri(url, UriKind.Absolute);
                return(new HttpRequestMessage(HttpUtilities.GetHttpMethod(context.Request.Method), uri)
                {
                    Version = httpVersion
                });
            }

            var transformContext = new RequestParametersTransformContext()
            {
                HttpContext = context,
                Version     = httpVersion,
                Method      = request.Method,
                Path        = request.Path,
                Query       = request.QueryString,
            };

            foreach (var transform in transforms)
            {
                transform.Apply(transformContext);
            }

            var targetUrl = UriHelper.BuildAbsolute(destinationScheme, destinationHost, destinationPathBase, transformContext.Path, transformContext.Query);

            Log.Proxying(_logger, targetUrl);
            var targetUri = new Uri(targetUrl, UriKind.Absolute);

            return(new HttpRequestMessage(HttpUtilities.GetHttpMethod(transformContext.Method), targetUri)
            {
                Version = transformContext.Version
            });
        }
 protected override string GetValue(RequestParametersTransformContext context)
 {
     return(_value);
 }
Exemple #8
0
 /// <summary>
 /// Transforms any of the available fields before building the outgoing request.
 /// </summary>
 public abstract void Apply(RequestParametersTransformContext context);
Exemple #9
0
        private HttpRequestMessage CreateRequestMessage(HttpContext context, string destinationAddress,
                                                        IReadOnlyList <RequestParametersTransform> requestTransforms, RequestProxyOptions requestOptions)
        {
            // "http://a".Length = 8
            if (destinationAddress == null || destinationAddress.Length < 8)
            {
                throw new ArgumentException(nameof(destinationAddress));
            }

            var upgradeFeature   = context.Features.Get <IHttpUpgradeFeature>();
            var upgradeHeader    = context.Request.Headers[HeaderNames.Upgrade].ToString();
            var isUpgradeRequest = (upgradeFeature?.IsUpgradableRequest ?? false)
                                   // Mitigate https://github.com/microsoft/reverse-proxy/issues/255, IIS considers all requests upgradeable.
                                   && (string.Equals("WebSocket", upgradeHeader, StringComparison.OrdinalIgnoreCase)
                                   // https://github.com/microsoft/reverse-proxy/issues/467 for kubernetes APIs
                                       || upgradeHeader.StartsWith("SPDY/", StringComparison.OrdinalIgnoreCase));

            // Default to HTTP/1.1 for proxying upgradeable requests. This is already the default as of .NET Core 3.1
            // Otherwise request what's set in proxyOptions (e.g. default HTTP/2) and let HttpClient negotiate the protocol
            // based on VersionPolicy (for .NET 5 and higher). For example, downgrading to HTTP/1.1 if it cannot establish HTTP/2 with the target.
            // This is done without extra round-trips thanks to ALPN. We can detect a downgrade after calling HttpClient.SendAsync
            // (see Step 3 below). TBD how this will change when HTTP/3 is supported.
            var httpVersion = isUpgradeRequest ? ProtocolHelper.Http11Version : (requestOptions.Version ?? DefaultVersion);

#if NET
            var httpVersionPolicy = isUpgradeRequest ? HttpVersionPolicy.RequestVersionOrLower : (requestOptions.VersionPolicy ?? DefaultVersionPolicy);
#endif

            // TODO Perf: We could probably avoid splitting this and just append the final path and query
            UriHelper.FromAbsolute(destinationAddress, out var destinationScheme, out var destinationHost, out var destinationPathBase, out _, out _); // Query and Fragment are not supported here.

            var request = context.Request;
            if (requestTransforms.Count == 0)
            {
                var url = UriHelper.BuildAbsolute(destinationScheme, destinationHost, destinationPathBase, request.Path, request.QueryString);
                Log.Proxying(_logger, url);
                var uri = new Uri(url, UriKind.Absolute);
                return(new HttpRequestMessage(HttpUtilities.GetHttpMethod(context.Request.Method), uri)
                {
                    Version = httpVersion,
#if NET
                    VersionPolicy = httpVersionPolicy,
#endif
                });
            }

            var transformContext = new RequestParametersTransformContext()
            {
                HttpContext = context,
                Version     = httpVersion,
                Method      = request.Method,
                Path        = request.Path,
                Query       = new QueryTransformContext(request),
#if NET
                VersionPolicy = httpVersionPolicy,
#endif
            };
            foreach (var requestTransform in requestTransforms)
            {
                requestTransform.Apply(transformContext);
            }

            var targetUrl = UriHelper.BuildAbsolute(destinationScheme, destinationHost, destinationPathBase, transformContext.Path, transformContext.Query.QueryString);
            Log.Proxying(_logger, targetUrl);
            var targetUri = new Uri(targetUrl, UriKind.Absolute);
            return(new HttpRequestMessage(HttpUtilities.GetHttpMethod(transformContext.Method), targetUri)
            {
                Version = transformContext.Version,
#if NET
                VersionPolicy = transformContext.VersionPolicy,
#endif
            });
        }