feat: support websockets
This commit is contained in:
parent
5e19348a11
commit
255b273f65
2 changed files with 77 additions and 3 deletions
9
VRCAuthProxy/HttpClientCookieContainer.cs
Normal file
9
VRCAuthProxy/HttpClientCookieContainer.cs
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
using System.Net;
|
||||
|
||||
namespace VRCAuthProxy;
|
||||
|
||||
class HttpClientCookieContainer(HttpClientHandler handler) : HttpClient(handler)
|
||||
{
|
||||
|
||||
public CookieContainer CookieContainer => handler.CookieContainer;
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
using System.Net.Http.Json;
|
||||
using System.Net.WebSockets;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
|
|
@ -13,7 +14,9 @@ using VRCAuthProxy.types;
|
|||
using HttpMethod = System.Net.Http.HttpMethod;
|
||||
using User = VRCAuthProxy.types.User;
|
||||
|
||||
var apiAccounts = new List<HttpClient>();
|
||||
string userAgent = "VRCAuthProxy V1.0.0 (https://github.com/PrideVRCommunity/VRCAuthProxy)";
|
||||
|
||||
var apiAccounts = new List<HttpClientCookieContainer>();
|
||||
|
||||
|
||||
|
||||
|
|
@ -29,6 +32,7 @@ void RotateAccount()
|
|||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
var app = builder.Build();
|
||||
app.UseWebSockets();
|
||||
|
||||
Config.Instance.Accounts.ForEach(async account =>
|
||||
{
|
||||
|
|
@ -39,12 +43,12 @@ Config.Instance.Accounts.ForEach(async account =>
|
|||
{
|
||||
CookieContainer = cookieContainer
|
||||
};
|
||||
var httpClient = new HttpClient(handler)
|
||||
var httpClient = new HttpClientCookieContainer(handler)
|
||||
{
|
||||
BaseAddress = new Uri("https://api.vrchat.cloud/api/1")
|
||||
|
||||
};
|
||||
httpClient.DefaultRequestHeaders.Add("User-Agent", "VRCAuthProxy V1.0.0 (https://github.com/PrideVRCommunity/VRCAuthProxy)");
|
||||
httpClient.DefaultRequestHeaders.Add("User-Agent", userAgent);
|
||||
|
||||
Console.WriteLine($"Creating API for {account.username}");
|
||||
|
||||
|
|
@ -106,6 +110,67 @@ app.MapGet("/rotate", () =>
|
|||
RotateAccount();
|
||||
return "Rotated account";
|
||||
});
|
||||
|
||||
// Proxy the websocket
|
||||
app.Use(async (context, next) =>
|
||||
{
|
||||
if (context.WebSockets.IsWebSocketRequest)
|
||||
{
|
||||
// api returns with {"err":"no authToken"}
|
||||
if (apiAccounts.Count == 0)
|
||||
{
|
||||
context.Response.StatusCode = 500;
|
||||
await context.Response.WriteAsync("No accounts available");
|
||||
return;
|
||||
}
|
||||
|
||||
var account = apiAccounts.First();
|
||||
var authCookie = account.CookieContainer.GetCookies(new Uri("https://api.vrchat.cloud"))["auth"]?.Value;
|
||||
|
||||
if (string.IsNullOrEmpty(authCookie))
|
||||
{
|
||||
context.Response.StatusCode = 401;
|
||||
await context.Response.WriteAsync("Authentication token not found");
|
||||
return;
|
||||
}
|
||||
|
||||
var clientWebSocket = await context.WebSockets.AcceptWebSocketAsync();
|
||||
using (var serverWebSocket = new ClientWebSocket())
|
||||
{
|
||||
serverWebSocket.Options.Cookies = account.CookieContainer;
|
||||
serverWebSocket.Options.SetRequestHeader("User-Agent", userAgent);
|
||||
await serverWebSocket.ConnectAsync(new Uri($"wss://vrchat.com/?authToken={authCookie}"), CancellationToken.None);
|
||||
|
||||
var buffer = new byte[8192];
|
||||
async Task ProxyData(WebSocket source, WebSocket target)
|
||||
{
|
||||
while (source.State == WebSocketState.Open && target.State == WebSocketState.Open)
|
||||
{
|
||||
var result = await source.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
|
||||
if (result.MessageType == WebSocketMessageType.Close)
|
||||
{
|
||||
await target.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
|
||||
break;
|
||||
}
|
||||
await target.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count), result.MessageType, result.EndOfMessage, CancellationToken.None);
|
||||
}
|
||||
}
|
||||
|
||||
var proxyTasks = new[]
|
||||
{
|
||||
ProxyData(clientWebSocket, serverWebSocket),
|
||||
ProxyData(serverWebSocket, clientWebSocket)
|
||||
};
|
||||
|
||||
await Task.WhenAny(proxyTasks);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await next();
|
||||
}
|
||||
});
|
||||
|
||||
// Proxy all requests starting with /api/1 to the VRChat API
|
||||
app.Use(async (context, next) =>
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue