Ejemplo n.º 1
0
 private static ProxyOptions CreateFrom(
     ProxyOptions old,
     bool?shouldAddForwardedHeaders = null,
     Func <HttpContext, Exception, Task> handleFailure          = null,
     Func <HttpContext, HttpRequestMessage, Task> beforeSend    = null,
     Func <HttpContext, HttpResponseMessage, Task> afterReceive = null)
 {
     return(new ProxyOptions(
                shouldAddForwardedHeaders ?? old.ShouldAddForwardedHeaders,
                handleFailure ?? old.HandleFailure,
                beforeSend ?? old.BeforeSend,
                afterReceive ?? old.AfterReceive));
 }
Ejemplo n.º 2
0
        internal static async Task ExecuteWsProxyOperationAsync(this HttpContext context, string uri, ProxyOptions options = null)
        {
            using (var socketToEndpoint = new ClientWebSocket())
            {
                foreach (var protocol in context.WebSockets.WebSocketRequestedProtocols)
                {
                    socketToEndpoint.Options.AddSubProtocol(protocol);
                }

                foreach (var headerEntry in context.Request.Headers)
                {
                    if (!Helpers.WebSocketNotForwardedHeaders.Contains(headerEntry.Key, StringComparer.OrdinalIgnoreCase))
                    {
                        socketToEndpoint.Options.SetRequestHeader(headerEntry.Key, headerEntry.Value);
                    }
                }

                // TODO: Add a proxy options for keep alive and set it here.
                //client.Options.KeepAliveInterval = proxyService.Options.WebSocketKeepAliveInterval.Value;

                // TODO make a proxy option action to edit the web socket options.

                await socketToEndpoint.ConnectAsync(new Uri(uri), context.RequestAborted);

                using (var socketToClient = await context.WebSockets.AcceptWebSocketAsync(socketToEndpoint.SubProtocol))
                {
                    // TODO: Add a buffer size option and set it here.
                    var bufferSize = 4096;
                    await Task.WhenAll(PumpWebSocket(socketToEndpoint, socketToClient, bufferSize, context.RequestAborted), PumpWebSocket(socketToClient, socketToEndpoint, bufferSize, context.RequestAborted));
                }
            }
        }
Ejemplo n.º 3
0
        internal static async Task ExecuteProxyOperation(HttpContext context, string uri, ProxyOptions options = null)
        {
            try
            {
                var proxiedRequest = context.CreateProxiedHttpRequest(uri, options?.ShouldAddForwardedHeaders ?? true);

                if (options?.BeforeSend != null)
                {
                    await options.BeforeSend(context, proxiedRequest).ConfigureAwait(false);
                }
                var proxiedResponse = await context.SendProxiedHttpRequest(proxiedRequest).ConfigureAwait(false);

                if (options?.AfterReceive != null)
                {
                    await options.AfterReceive(context, proxiedResponse).ConfigureAwait(false);
                }
                await context.WriteProxiedHttpResponse(proxiedResponse).ConfigureAwait(false);
            }
            catch (Exception e)
            {
                if (options?.HandleFailure == null)
                {
                    // If the failures are not caught, then write a generic response.
                    context.Response.StatusCode = 502;
                    await context.Response.WriteAsync($"Request could not be proxied.\n\n{e.Message}\n\n{e.StackTrace}.").ConfigureAwait(false);

                    return;
                }

                await options.HandleFailure(context, e).ConfigureAwait(false);
            }
        }
Ejemplo n.º 4
0
        internal static async Task ExecuteProxyOperationAsync(this HttpContext context, string uri, ProxyOptions options = null)
        {
            try
            {
                if (context.WebSockets.IsWebSocketRequest)
                {
                    if (!uri.StartsWith("ws", System.StringComparison.OrdinalIgnoreCase))
                    {
                        throw new InvalidOperationException("A WebSocket request must forward to a WebSocket (ws[s]) endpoint.");
                    }

                    await context.ExecuteWsProxyOperationAsync(uri, options).ConfigureAwait(false);

                    return;
                }

                // Assume HTTP if not WebSocket.
                if (!uri.StartsWith("http", System.StringComparison.OrdinalIgnoreCase))
                {
                    throw new InvalidOperationException("An HTTP request must forward to an HTTP (http[s]) endpoint.");
                }

                await context.ExecuteHttpProxyOperationAsync(uri, options).ConfigureAwait(false);
            }
            catch (Exception e)
            {
                if (!context.Response.HasStarted)
                {
                    if (options?.HandleFailure == null)
                    {
                        // If the failures are not caught, then write a generic response.
                        context.Response.StatusCode = 502;
                        await context.Response.WriteAsync($"Request could not be proxied.\n\n{e.Message}\n\n{e.StackTrace}").ConfigureAwait(false);

                        return;
                    }

                    await options.HandleFailure(context, e).ConfigureAwait(false);
                }
            }
        }
 /// <summary>
 /// A <see cref="Controller"/> extension method which allows for a single, simple call to use a proxy
 /// in existing controllers.
 /// </summary>
 /// <param name="controller">The calling controller.</param>
 /// <param name="uri">The URI to proxy.</param>
 /// <param name="options">Extra options to apply during proxying.</param>
 /// <returns>
 /// A <see cref="Task"/> which, upon completion, has proxied the specified address and copied the response contents into
 /// the response for the <see cref="HttpContext"/>.
 /// </returns>
 public static Task ProxyAsync(this ControllerBase controller, string uri, ProxyOptions options = null)
 {
     return(Helpers.ExecuteProxyOperation(controller.HttpContext, uri, options));
 }
 // Provides the "default" implementation for `UseProxy` where the proxied address is computed synchronously.
 private static void UseProxy_GpaSync(this IApplicationBuilder app, string endpoint, Func <HttpContext, IDictionary <string, object>, string> getProxiedAddress, ProxyOptions options = null)
 {
     app.UseRouter(builder => {
         builder.MapMiddlewareRoute(endpoint, proxyApp => {
             proxyApp.Run(async context => {
                 var uri = getProxiedAddress(context, context.GetRouteData().Values.ToDictionary(v => v.Key, v => v.Value));
                 await Helpers.ExecuteProxyOperation(context, uri, options);
             });
         });
     });
 }
 /// <summary>
 /// Middleware which creates an ad hoc proxy over a specified endpoint.
 /// </summary>
 /// <param name="app">The ASP.NET <see cref="IApplicationBuilder"/>.</param>
 /// <param name="endpoint">The local route endpoint.</param>
 /// <param name="getProxiedAddress">A lambda { () => <see cref="string"/> } which returns the address to which the request is proxied.</param>
 /// <param name="options">Extra options to apply during proxying.</param>
 public static void UseProxy(this IApplicationBuilder app, string endpoint, Func <string> getProxiedAddress, ProxyOptions options = null)
 {
     UseProxy_GpaSync(
         app,
         endpoint,
         (context, args) => getProxiedAddress(),
         options);
 }
 /// <summary>
 /// Middleware which creates an ad hoc proxy over a specified endpoint.
 /// </summary>
 /// <param name="app">The ASP.NET <see cref="IApplicationBuilder"/>.</param>
 /// <param name="endpoint">The local route endpoint.</param>
 /// <param name="getProxiedAddress">A lambda { (args) => <see cref="Task{String}"/> } which returns the address to which the request is proxied.</param>
 /// <param name="options">Extra options to apply during proxying.</param>
 public static void UseProxy(this IApplicationBuilder app, string endpoint, Func <IDictionary <string, object>, Task <string> > getProxiedAddress, ProxyOptions options = null)
 {
     UseProxy_GpaAsync(
         app,
         endpoint,
         (context, args) => getProxiedAddress(args),
         options);
 }
 /// <summary>
 /// Terminating middleware which creates a proxy over a specified endpoint.
 /// </summary>
 /// <param name="app">The ASP.NET <see cref="IApplicationBuilder"/>.</param>
 /// <param name="getProxiedAddress">A lambda { (context) => <see cref="string"/> } which returns the address to which the request is proxied.</param>
 /// <param name="options">Extra options to apply during proxying.</param>
 public static void RunProxy(this IApplicationBuilder app, Func <HttpContext, string> getProxiedAddress, ProxyOptions options = null)
 {
     app.Run(context =>
     {
         return(context.ExecuteProxyOperationAsync($"{getProxiedAddress(context)}{context.Request.Path}", options));
     });
 }
Ejemplo n.º 10
0
        internal static async Task ExecuteHttpProxyOperationAsync(this HttpContext context, string uri, ProxyOptions options = null)
        {
            // If `true`, this proxy call has been intercepted.
            if (options?.Intercept != null && await options.Intercept(context))
            {
                return;
            }

            var proxiedRequest = context.CreateProxiedHttpRequest(uri, options?.ShouldAddForwardedHeaders ?? true);

            if (options?.BeforeSend != null)
            {
                await options.BeforeSend(context, proxiedRequest).ConfigureAwait(false);
            }
            var proxiedResponse = await context
                                  .SendProxiedHttpRequestAsync(proxiedRequest, options?.HttpClientName ?? Helpers.HttpProxyClientName)
                                  .ConfigureAwait(false);

            if (options?.AfterReceive != null)
            {
                await options.AfterReceive(context, proxiedResponse).ConfigureAwait(false);
            }
            await context.WriteProxiedHttpResponseAsync(proxiedResponse).ConfigureAwait(false);
        }