Ejemplo n.º 1
0
        public ProxyConfigManager(
            ILogger <ProxyConfigManager> logger,
            IProxyConfigProvider provider,
            IClusterManager clusterManager,
            IRouteManager routeManager,
            IEnumerable <IProxyConfigFilter> filters,
            IConfigValidator configValidator,
            ProxyEndpointFactory proxyEndpointFactory,
            ITransformBuilder transformBuilder,
            IProxyHttpClientFactory httpClientFactory,
            IActiveHealthCheckMonitor activeHealthCheckMonitor)
        {
            _logger                   = logger ?? throw new ArgumentNullException(nameof(logger));
            _provider                 = provider ?? throw new ArgumentNullException(nameof(provider));
            _clusterManager           = clusterManager ?? throw new ArgumentNullException(nameof(clusterManager));
            _routeManager             = routeManager ?? throw new ArgumentNullException(nameof(routeManager));
            _filters                  = filters ?? throw new ArgumentNullException(nameof(filters));
            _configValidator          = configValidator ?? throw new ArgumentNullException(nameof(configValidator));
            _proxyEndpointFactory     = proxyEndpointFactory ?? throw new ArgumentNullException(nameof(proxyEndpointFactory));
            _transformBuilder         = transformBuilder ?? throw new ArgumentNullException(nameof(transformBuilder));
            _httpClientFactory        = httpClientFactory ?? throw new ArgumentNullException(nameof(httpClientFactory));
            _activeHealthCheckMonitor = activeHealthCheckMonitor ?? throw new ArgumentNullException(nameof(activeHealthCheckMonitor));

            _conventions   = new List <Action <EndpointBuilder> >();
            DefaultBuilder = new ReverseProxyConventionBuilder(_conventions);

            _changeToken = new CancellationChangeToken(_cancellationTokenSource.Token);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Proxies the incoming request to the upstream server, and the response back to our client.
        /// </summary>
        /// <remarks>
        /// In what follows, as well as throughout in Reverse Proxy, we consider
        /// the following picture as illustrative of the Proxy.
        /// <code>
        ///      +-------------------+
        ///      |  Upstream server  +
        ///      +-------------------+
        ///            ▲       |
        ///        (b) |       | (c)
        ///            |       ▼
        ///      +-------------------+
        ///      |      Proxy        +
        ///      +-------------------+
        ///            ▲       |
        ///        (a) |       | (d)
        ///            |       ▼
        ///      +-------------------+
        ///      | Downstream client +
        ///      +-------------------+
        /// </code>
        ///
        /// (a) and (b) show the *request* path, going *upstream* from the client to the target.
        /// (c) and (d) show the *response* path, going *downstream* from the target back to the client.
        /// </remarks>
        /// <param name="longCancellation">This should be linked to a client disconnect notification like <see cref="HttpContext.RequestAborted"/>
        /// to avoid leaking long running requests.</param>
        public Task ProxyAsync(
            HttpContext context,
            string destinationPrefix,
            Transforms transforms,
            IProxyHttpClientFactory httpClientFactory,
            ProxyTelemetryContext proxyTelemetryContext,
            CancellationToken shortCancellation,
            CancellationToken longCancellation)
        {
            Contracts.CheckValue(context, nameof(context));
            Contracts.CheckValue(destinationPrefix, nameof(destinationPrefix));
            Contracts.CheckValue(transforms, nameof(transforms));
            Contracts.CheckValue(httpClientFactory, nameof(httpClientFactory));

            // :::::::::::::::::::::::::::::::::::::::::::::
            // :: Step 1: Create outgoing HttpRequestMessage
            var upgradeFeature = context.Features.Get <IHttpUpgradeFeature>();
            var isUpgrade      = upgradeFeature?.IsUpgradableRequest ?? false;
            // Default to HTTP/1.1 for proxying upgradable 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 version = isUpgrade ? ProtocolHelper.Http11Version : ProtocolHelper.Http2Version;

            var request = CreateRequestMessage(context, destinationPrefix, version, transforms.RequestTransforms);

            if (isUpgrade)
            {
                return(UpgradableProxyAsync(context, upgradeFeature, request, transforms, httpClientFactory.CreateUpgradableClient(), proxyTelemetryContext, shortCancellation, longCancellation));
            }
            else
            {
                return(NormalProxyAsync(context, request, transforms, httpClientFactory.CreateNormalClient(), proxyTelemetryContext, shortCancellation, longCancellation));
            }
        }
Ejemplo n.º 3
0
        public ClusterInfo(string clusterId, IDestinationManager destinationManager, IProxyHttpClientFactory proxyHttpClientFactory)
        {
            ClusterId              = clusterId ?? throw new ArgumentNullException(nameof(clusterId));
            DestinationManager     = destinationManager ?? throw new ArgumentNullException(nameof(destinationManager));
            ProxyHttpClientFactory = proxyHttpClientFactory ?? throw new ArgumentNullException(nameof(proxyHttpClientFactory));

            DynamicState = CreateDynamicStateQuery();
        }
Ejemplo n.º 4
0
        public BackendInfo(string backendId, IEndpointManager endpointManager, IProxyHttpClientFactory proxyHttpClientFactory)
        {
            Contracts.CheckNonEmpty(backendId, nameof(backendId));
            Contracts.CheckValue(endpointManager, nameof(endpointManager));
            Contracts.CheckValue(proxyHttpClientFactory, nameof(proxyHttpClientFactory));

            BackendId              = backendId;
            EndpointManager        = endpointManager;
            ProxyHttpClientFactory = proxyHttpClientFactory;

            DynamicState = CreateDynamicStateQuery();
        }
Ejemplo n.º 5
0
        public BackendInfo(string backendId, IDestinationManager destinationManager, IProxyHttpClientFactory proxyHttpClientFactory)
        {
            Contracts.CheckNonEmpty(backendId, nameof(backendId));
            Contracts.CheckValue(destinationManager, nameof(destinationManager));
            Contracts.CheckValue(proxyHttpClientFactory, nameof(proxyHttpClientFactory));

            BackendId              = backendId;
            DestinationManager     = destinationManager;
            ProxyHttpClientFactory = proxyHttpClientFactory;

            DynamicState = CreateDynamicStateQuery();
        }
Ejemplo n.º 6
0
    public DynamicHttpProxyInterceptor(
        DynamicHttpProxyInterceptorClientProxy <TService> interceptorClientProxy,
        IOptions <AbpHttpClientOptions> clientOptions,
        IProxyHttpClientFactory httpClientFactory,
        IRemoteServiceConfigurationProvider remoteServiceConfigurationProvider,
        IApiDescriptionFinder apiDescriptionFinder)
    {
        InterceptorClientProxy             = interceptorClientProxy;
        HttpClientFactory                  = httpClientFactory;
        RemoteServiceConfigurationProvider = remoteServiceConfigurationProvider;
        ApiDescriptionFinder               = apiDescriptionFinder;
        ClientOptions = clientOptions.Value;

        Logger = NullLogger <DynamicHttpProxyInterceptor <TService> > .Instance;
    }
Ejemplo n.º 7
0
        public ProxyConfigManager(
            ILogger <ProxyConfigManager> logger,
            IProxyConfigProvider provider,
            IRuntimeRouteBuilder routeEndpointBuilder,
            IClusterManager clusterManager,
            IRouteManager routeManager,
            IEnumerable <IProxyConfigFilter> filters,
            IConfigValidator configValidator,
            IProxyHttpClientFactory httpClientFactory)
        {
            _logger               = logger ?? throw new ArgumentNullException(nameof(logger));
            _provider             = provider ?? throw new ArgumentNullException(nameof(provider));
            _routeEndpointBuilder = routeEndpointBuilder ?? throw new ArgumentNullException(nameof(routeEndpointBuilder));
            _clusterManager       = clusterManager ?? throw new ArgumentNullException(nameof(clusterManager));
            _routeManager         = routeManager ?? throw new ArgumentNullException(nameof(routeManager));
            _filters              = filters ?? throw new ArgumentNullException(nameof(filters));
            _configValidator      = configValidator ?? throw new ArgumentNullException(nameof(configValidator));
            _httpClientFactory    = httpClientFactory ?? throw new ArgumentNullException(nameof(httpClientFactory));

            _changeToken = new CancellationChangeToken(_cancellationTokenSource.Token);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Proxies the incoming request to the upstream server, and the response back to our client.
        /// </summary>
        /// <remarks>
        /// In what follows, as well as throughout in Reverse Proxy, we consider
        /// the following picture as illustrative of the Proxy.
        /// <code>
        ///      +-------------------+
        ///      |  Upstream server  +
        ///      +-------------------+
        ///            ▲       |
        ///        (b) |       | (c)
        ///            |       ▼
        ///      +-------------------+
        ///      |      Proxy        +
        ///      +-------------------+
        ///            ▲       |
        ///        (a) |       | (d)
        ///            |       ▼
        ///      +-------------------+
        ///      | Downstream client +
        ///      +-------------------+
        /// </code>
        ///
        /// (a) and (b) show the *request* path, going *upstream* from the client to the target.
        /// (c) and (d) show the *response* path, going *downstream* from the target back to the client.
        /// </remarks>
        /// <param name="longCancellation">This should be linked to a client disconnect notification like <see cref="HttpContext.RequestAborted"/>
        /// to avoid leaking long running requests.</param>
        public Task ProxyAsync(
            HttpContext context,
            Uri targetUri,
            IProxyHttpClientFactory httpClientFactory,
            ProxyTelemetryContext proxyTelemetryContext,
            CancellationToken shortCancellation,
            CancellationToken longCancellation)
        {
            Contracts.CheckValue(context, nameof(context));
            Contracts.CheckValue(targetUri, nameof(targetUri));
            Contracts.CheckValue(httpClientFactory, nameof(httpClientFactory));

            var upgradeFeature = context.Features.Get <IHttpUpgradeFeature>();

            if (upgradeFeature == null || !upgradeFeature.IsUpgradableRequest)
            {
                return(NormalProxyAsync(context, targetUri, httpClientFactory.CreateNormalClient(), proxyTelemetryContext, shortCancellation, longCancellation));
            }
            else
            {
                return(UpgradableProxyAsync(context, upgradeFeature, targetUri, httpClientFactory.CreateUpgradableClient(), proxyTelemetryContext, shortCancellation, longCancellation));
            }
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Proxies the incoming request to the upstream server, and the response back to our client.
        /// </summary>
        /// <remarks>
        /// In what follows, as well as throughout in Reverse Proxy, we consider
        /// the following picture as illustrative of the Proxy.
        /// <code>
        ///      +-------------------+
        ///      |  Upstream server  +
        ///      +-------------------+
        ///            ▲       |
        ///        (b) |       | (c)
        ///            |       ▼
        ///      +-------------------+
        ///      |      Proxy        +
        ///      +-------------------+
        ///            ▲       |
        ///        (a) |       | (d)
        ///            |       ▼
        ///      +-------------------+
        ///      | Downstream client +
        ///      +-------------------+
        /// </code>
        ///
        /// (a) and (b) show the *request* path, going *upstream* from the client to the target.
        /// (c) and (d) show the *response* path, going *downstream* from the target back to the client.
        /// </remarks>
        /// <param name="longCancellation">This should be linked to a client disconnect notification like <see cref="HttpContext.RequestAborted"/>
        /// to avoid leaking long running requests.</param>
        public Task ProxyAsync(
            HttpContext context,
            string destinationPrefix,
            Transforms transforms,
            IProxyHttpClientFactory httpClientFactory,
            ProxyTelemetryContext proxyTelemetryContext,
            CancellationToken shortCancellation,
            CancellationToken longCancellation)
        {
            _ = context ?? throw new ArgumentNullException(nameof(context));
            _ = destinationPrefix ?? throw new ArgumentNullException(nameof(destinationPrefix));
            _ = transforms ?? throw new ArgumentNullException(nameof(transforms));
            _ = httpClientFactory ?? throw new ArgumentNullException(nameof(httpClientFactory));

            // :::::::::::::::::::::::::::::::::::::::::::::
            // :: Step 1: Create outgoing HttpRequestMessage
            var upgradeFeature = context.Features.Get <IHttpUpgradeFeature>();
            var isUpgrade      = (upgradeFeature?.IsUpgradableRequest ?? false)
                                 // Mitigate https://github.com/microsoft/reverse-proxy/issues/255, IIS considers all requests upgradeable.
                                 && string.Equals("WebSocket", context.Request.Headers[HeaderNames.Upgrade], StringComparison.OrdinalIgnoreCase);
            // 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 version = isUpgrade ? ProtocolHelper.Http11Version : ProtocolHelper.Http2Version;

            var request = CreateRequestMessage(context, destinationPrefix, version, transforms.RequestTransforms);

            if (isUpgrade)
            {
                return(UpgradableProxyAsync(context, upgradeFeature, request, transforms, httpClientFactory.CreateClient(), proxyTelemetryContext, shortCancellation, longCancellation));
            }
            else
            {
                return(NormalProxyAsync(context, request, transforms, httpClientFactory.CreateClient(), proxyTelemetryContext, shortCancellation, longCancellation));
            }
        }
Ejemplo n.º 10
0
        public ProxyMiddleware(RequestDelegate nextMiddleware, T serviceProxy, ILogger <ProxyMiddleware <T> > logger, IProxyHttpClientFactory clientFactory)
        {
            _nextMiddleware = nextMiddleware;
            _serviceProxy   = serviceProxy;
            _logger         = logger;

            _httpClient = clientFactory.Create(serviceProxy.DisableTlsVerification());
        }