-
-
Notifications
You must be signed in to change notification settings - Fork 83
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #26 from twitchax/ws-support
WebSocket Support
- Loading branch information
Showing
17 changed files
with
902 additions
and
187 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
TODO: | ||
* Should UseProxy require the user to set all of the proxies at once? YES, in 4.0.0...`UseProxies` with builders. | ||
* Remove the [ProxyRoute] attribute? Maybe, in 4.0.0. If we keep it, change it to `UseStaticProxies`, and somehow return options? | ||
* Round robin helper, and protocol helper for `RunProxy`? Maybe in 4.0.0. | ||
* Add options for WebSocket calls. | ||
* Make options handlers called `Async`? | ||
* Allow the user to set options via a lambda for builder purposes? | ||
* Add a `RunProxy` that takes a `getProxiedAddress` as a `Task<string>`. | ||
|
||
Some ideas of how `UseProxies` should work in 4.0.0. | ||
|
||
```csharp | ||
|
||
// Custom top-level extension method. | ||
app.UseProxies(proxies => | ||
{ | ||
proxies.Map("/route/thingy") | ||
.ToHttp("http://mysite.com/") // OR To(http, ws) | ||
.WithOption1(); | ||
|
||
// OR | ||
proxies.Map("/route/thingy", proxy => | ||
{ | ||
// Make sure the proxy builder has HttpContext on it. | ||
proxy.ToHttp("http://mysite.com") | ||
.WithOption1(...); | ||
|
||
proxy.ToWs(...); | ||
}); | ||
}); | ||
|
||
// OR? | ||
// Piggy-back on the ASP.NET Core 3 endpoints pattern. | ||
app.UseEndpoints(endpoints => | ||
{ | ||
endpoints.Map("/my/path", context => | ||
{ | ||
return context.ProxyAsync("http://mysite.com", options => | ||
{ | ||
options.WithOption1(); | ||
}); | ||
|
||
// OR? | ||
return context.HttpProxyTo("http://mysite.com", options => | ||
{ | ||
options.WithOption1(); | ||
}); | ||
|
||
// OR, maybe there is an `HttpProxyTo` and `WsProxyTo`, and a `ProxyTo` that does its best to decide. | ||
}); | ||
}) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
using Microsoft.AspNetCore.Http; | ||
using System; | ||
using System.Threading.Tasks; | ||
|
||
namespace AspNetCore.Proxy | ||
{ | ||
internal static class Extensions | ||
{ | ||
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); | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.