intials app
This commit is contained in:
9
lstWrapper/LstWrapper.csproj
Normal file
9
lstWrapper/LstWrapper.csproj
Normal file
@@ -0,0 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
166
lstWrapper/Program.cs
Normal file
166
lstWrapper/Program.cs
Normal file
@@ -0,0 +1,166 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.WebSockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.AspNetCore.HttpOverrides;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
builder.Services.AddHttpClient("NodeApp", client =>
|
||||
{
|
||||
client.BaseAddress = new Uri("http://localhost:4000");
|
||||
|
||||
});
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Enable WebSocket support
|
||||
app.UseWebSockets();
|
||||
|
||||
// Logging method
|
||||
void LogToFile(string message)
|
||||
{
|
||||
try
|
||||
{
|
||||
string logDir = Path.Combine(AppContext.BaseDirectory, "logs");
|
||||
Directory.CreateDirectory(logDir);
|
||||
string logFilePath = Path.Combine(logDir, "proxy_log.txt");
|
||||
File.AppendAllText(logFilePath, $"{DateTime.UtcNow}: {message}{Environment.NewLine}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Handle potential errors writing to log file
|
||||
Console.WriteLine($"Logging error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
app.UseForwardedHeaders(new ForwardedHeadersOptions
|
||||
{
|
||||
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto,
|
||||
// Increase the limit if you have multiple proxies
|
||||
ForwardLimit = 2
|
||||
});
|
||||
// Middleware to handle WebSocket requests
|
||||
app.Use(async (context, next) =>
|
||||
{
|
||||
if (context.WebSockets.IsWebSocketRequest && context.Request.Path.StartsWithSegments("/ws"))
|
||||
{
|
||||
// LogToFile($"WebSocket request received for path: {context.Request.Path}");
|
||||
|
||||
try
|
||||
{
|
||||
var backendUri = new UriBuilder("ws", "localhost", 4000)
|
||||
{
|
||||
Path = context.Request.Path,
|
||||
Query = context.Request.QueryString.ToString()
|
||||
}.Uri;
|
||||
|
||||
using var backendSocket = new ClientWebSocket();
|
||||
await backendSocket.ConnectAsync(backendUri, context.RequestAborted);
|
||||
|
||||
using var frontendSocket = await context.WebSockets.AcceptWebSocketAsync();
|
||||
var cts = new CancellationTokenSource();
|
||||
|
||||
// WebSocket forwarding tasks
|
||||
var forwardToBackend = ForwardWebSocketAsync(frontendSocket, backendSocket, cts.Token);
|
||||
var forwardToFrontend = ForwardWebSocketAsync(backendSocket, frontendSocket, cts.Token);
|
||||
|
||||
await Task.WhenAny(forwardToBackend, forwardToFrontend);
|
||||
cts.Cancel();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//LogToFile($"WebSocket proxy error: {ex.Message}");
|
||||
context.Response.StatusCode = (int)HttpStatusCode.BadGateway;
|
||||
await context.Response.WriteAsync($"WebSocket proxy error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await next();
|
||||
}
|
||||
});
|
||||
|
||||
// Middleware to handle HTTP requests
|
||||
app.Use(async (context, next) =>
|
||||
{
|
||||
if (context.WebSockets.IsWebSocketRequest)
|
||||
{
|
||||
await next();
|
||||
return;
|
||||
}
|
||||
|
||||
var client = context.RequestServices.GetRequiredService<IHttpClientFactory>().CreateClient("NodeApp");
|
||||
|
||||
try
|
||||
{
|
||||
var request = new HttpRequestMessage(new HttpMethod(context.Request.Method),
|
||||
context.Request.Path + context.Request.QueryString);
|
||||
|
||||
foreach (var header in context.Request.Headers)
|
||||
{
|
||||
if (!request.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()))
|
||||
{
|
||||
request.Content ??= new StreamContent(context.Request.Body);
|
||||
request.Content.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
if (context.Request.ContentLength > 0 && request.Content == null)
|
||||
{
|
||||
request.Content = new StreamContent(context.Request.Body);
|
||||
}
|
||||
|
||||
var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, context.RequestAborted);
|
||||
context.Response.StatusCode = (int)response.StatusCode;
|
||||
|
||||
foreach (var header in response.Headers)
|
||||
{
|
||||
context.Response.Headers[header.Key] = header.Value.ToArray();
|
||||
}
|
||||
|
||||
foreach (var header in response.Content.Headers)
|
||||
{
|
||||
context.Response.Headers[header.Key] = header.Value.ToArray();
|
||||
}
|
||||
|
||||
context.Response.Headers.Remove("transfer-encoding");
|
||||
await response.Content.CopyToAsync(context.Response.Body);
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
LogToFile($"HTTP proxy error: {ex.Message}");
|
||||
context.Response.StatusCode = (int)HttpStatusCode.BadGateway;
|
||||
await context.Response.WriteAsync($"Backend request failed: {ex.Message}");
|
||||
}
|
||||
});
|
||||
|
||||
async Task ForwardWebSocketAsync(WebSocket source, WebSocket destination, CancellationToken cancellationToken)
|
||||
{
|
||||
var buffer = new byte[4 * 1024];
|
||||
try
|
||||
{
|
||||
while (source.State == WebSocketState.Open &&
|
||||
destination.State == WebSocketState.Open &&
|
||||
!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
var result = await source.ReceiveAsync(new ArraySegment<byte>(buffer), cancellationToken);
|
||||
if (result.MessageType == WebSocketMessageType.Close)
|
||||
{
|
||||
await destination.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "Closing", cancellationToken);
|
||||
break;
|
||||
}
|
||||
await destination.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count), result.MessageType, result.EndOfMessage, cancellationToken);
|
||||
}
|
||||
}
|
||||
catch (WebSocketException ex)
|
||||
{
|
||||
LogToFile($"WebSocket forwarding error: {ex.Message}");
|
||||
await destination.CloseOutputAsync(WebSocketCloseStatus.InternalServerError, "Error", cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
app.Run();
|
||||
65
lstWrapper/Program_proxy_backend.txt
Normal file
65
lstWrapper/Program_proxy_backend.txt
Normal file
@@ -0,0 +1,65 @@
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Configure clients
|
||||
builder.Services.AddHttpClient("GoBackend", client => {
|
||||
client.BaseAddress = new Uri("http://localhost:8080");
|
||||
});
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Handle trailing slash redirects
|
||||
app.Use(async (context, next) => {
|
||||
if (context.Request.Path.Equals("/lst", StringComparison.OrdinalIgnoreCase)) {
|
||||
context.Response.Redirect("/lst/", permanent: true);
|
||||
return;
|
||||
}
|
||||
await next();
|
||||
});
|
||||
|
||||
// Proxy all requests to Go backend
|
||||
app.Use(async (context, next) => {
|
||||
// Skip special paths
|
||||
if (context.Request.Path.StartsWithSegments("/.well-known")) {
|
||||
await next();
|
||||
return;
|
||||
}
|
||||
|
||||
var client = context.RequestServices.GetRequiredService<IHttpClientFactory>()
|
||||
.CreateClient("GoBackend");
|
||||
|
||||
try {
|
||||
var request = new HttpRequestMessage(
|
||||
new HttpMethod(context.Request.Method),
|
||||
context.Request.Path + context.Request.QueryString);
|
||||
|
||||
// Copy headers
|
||||
foreach (var header in context.Request.Headers) {
|
||||
if (!request.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray())) {
|
||||
request.Content ??= new StreamContent(context.Request.Body);
|
||||
request.Content.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
if (context.Request.ContentLength > 0) {
|
||||
request.Content = new StreamContent(context.Request.Body);
|
||||
}
|
||||
|
||||
var response = await client.SendAsync(request);
|
||||
context.Response.StatusCode = (int)response.StatusCode;
|
||||
|
||||
foreach (var header in response.Headers) {
|
||||
context.Response.Headers[header.Key] = header.Value.ToArray();
|
||||
}
|
||||
|
||||
if (response.Content.Headers.ContentType != null) {
|
||||
context.Response.ContentType = response.Content.Headers.ContentType.ToString();
|
||||
}
|
||||
|
||||
await response.Content.CopyToAsync(context.Response.Body);
|
||||
}
|
||||
catch (HttpRequestException) {
|
||||
context.Response.StatusCode = 502;
|
||||
}
|
||||
});
|
||||
|
||||
app.Run();
|
||||
65
lstWrapper/Program_vite_as_Static.txt
Normal file
65
lstWrapper/Program_vite_as_Static.txt
Normal file
@@ -0,0 +1,65 @@
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Configure clients
|
||||
builder.Services.AddHttpClient("GoBackend", client => {
|
||||
client.BaseAddress = new Uri("http://localhost:8080");
|
||||
});
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Handle trailing slash redirects
|
||||
app.Use(async (context, next) => {
|
||||
if (context.Request.Path.Equals("/lst", StringComparison.OrdinalIgnoreCase)) {
|
||||
context.Response.Redirect("/lst/", permanent: true);
|
||||
return;
|
||||
}
|
||||
await next();
|
||||
});
|
||||
|
||||
// Proxy all requests to Go backend
|
||||
app.Use(async (context, next) => {
|
||||
// Skip special paths
|
||||
if (context.Request.Path.StartsWithSegments("/.well-known")) {
|
||||
await next();
|
||||
return;
|
||||
}
|
||||
|
||||
var client = context.RequestServices.GetRequiredService<IHttpClientFactory>()
|
||||
.CreateClient("GoBackend");
|
||||
|
||||
try {
|
||||
var request = new HttpRequestMessage(
|
||||
new HttpMethod(context.Request.Method),
|
||||
context.Request.Path + context.Request.QueryString);
|
||||
|
||||
// Copy headers
|
||||
foreach (var header in context.Request.Headers) {
|
||||
if (!request.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray())) {
|
||||
request.Content ??= new StreamContent(context.Request.Body);
|
||||
request.Content.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
if (context.Request.ContentLength > 0) {
|
||||
request.Content = new StreamContent(context.Request.Body);
|
||||
}
|
||||
|
||||
var response = await client.SendAsync(request);
|
||||
context.Response.StatusCode = (int)response.StatusCode;
|
||||
|
||||
foreach (var header in response.Headers) {
|
||||
context.Response.Headers[header.Key] = header.Value.ToArray();
|
||||
}
|
||||
|
||||
if (response.Content.Headers.ContentType != null) {
|
||||
context.Response.ContentType = response.Content.Headers.ContentType.ToString();
|
||||
}
|
||||
|
||||
await response.Content.CopyToAsync(context.Response.Body);
|
||||
}
|
||||
catch (HttpRequestException) {
|
||||
context.Response.StatusCode = 502;
|
||||
}
|
||||
});
|
||||
|
||||
app.Run();
|
||||
23
lstWrapper/Properties/launchSettings.json
Normal file
23
lstWrapper/Properties/launchSettings.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "http://localhost:5015",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "https://localhost:7208;http://localhost:5015",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
8
lstWrapper/appsettings.Development.json
Normal file
8
lstWrapper/appsettings.Development.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
9
lstWrapper/appsettings.json
Normal file
9
lstWrapper/appsettings.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
40
lstWrapper/web.config
Normal file
40
lstWrapper/web.config
Normal file
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<system.webServer>
|
||||
<!-- Enable WebSockets -->
|
||||
<webSocket enabled="true" receiveBufferLimit="4194304" pingInterval="00:01:00" />
|
||||
|
||||
<rewrite>
|
||||
<rules>
|
||||
<!-- Proxy all requests starting with /lst/ to the .NET wrapper (port 4000) -->
|
||||
<rule name="Proxy to Wrapper" stopProcessing="true">
|
||||
<match url="^lst/(.*)" />
|
||||
<conditions>
|
||||
<!-- Skip this rule if it's a WebSocket request -->
|
||||
<add input="{HTTP_UPGRADE}" pattern="^WebSocket$" negate="true" />
|
||||
</conditions>
|
||||
<action type="Rewrite" url="http://localhost:4000/{R:1}" />
|
||||
<serverVariables>
|
||||
<set name="HTTP_X_FORWARDED_FOR" value="{REMOTE_ADDR}" />
|
||||
<set name="HTTP_X_REAL_IP" value="{REMOTE_ADDR}" />
|
||||
</serverVariables>
|
||||
</rule>
|
||||
</rules>
|
||||
</rewrite>
|
||||
|
||||
<staticContent>
|
||||
<mimeMap fileExtension=".js" mimeType="application/javascript" />
|
||||
<mimeMap fileExtension=".mjs" mimeType="application/javascript" />
|
||||
<mimeMap fileExtension=".css" mimeType="text/css" />
|
||||
<mimeMap fileExtension=".svg" mimeType="image/svg+xml" />
|
||||
</staticContent>
|
||||
|
||||
<handlers>
|
||||
<!-- Let AspNetCoreModule handle all requests -->
|
||||
<remove name="WebSocketHandler" />
|
||||
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
|
||||
</handlers>
|
||||
|
||||
<aspNetCore processPath="dotnet" arguments=".\lstWrapper.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" />
|
||||
</system.webServer>
|
||||
</configuration>
|
||||
6
lstWrapper/wwwroot/index.html
Normal file
6
lstWrapper/wwwroot/index.html
Normal file
@@ -0,0 +1,6 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<p>The new begining to lst</p>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user