initial commit
This commit is contained in:
commit
03e661a777
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
bin/
|
||||||
|
obj/
|
||||||
|
.idea/
|
||||||
|
log/
|
||||||
|
logs/
|
||||||
16
Fluzm.sln
Normal file
16
Fluzm.sln
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Fluzm", "Fluzm\Fluzm.csproj", "{7AEF72D2-CFE1-4A6C-B5E0-A4F9386F94CF}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{7AEF72D2-CFE1-4A6C-B5E0-A4F9386F94CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{7AEF72D2-CFE1-4A6C-B5E0-A4F9386F94CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{7AEF72D2-CFE1-4A6C-B5E0-A4F9386F94CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{7AEF72D2-CFE1-4A6C-B5E0-A4F9386F94CF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
43
Fluzm/Config.cs
Normal file
43
Fluzm/Config.cs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
using System;
|
||||||
|
using DTLib.Dtsod;
|
||||||
|
|
||||||
|
namespace Fluzm;
|
||||||
|
|
||||||
|
public class Config
|
||||||
|
{
|
||||||
|
public const int ActualVersion = 1;
|
||||||
|
|
||||||
|
public int Version = ActualVersion;
|
||||||
|
public string Address = "127.0.0.1";
|
||||||
|
public int Port = 8080;
|
||||||
|
|
||||||
|
public Config()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public Config(int version, string address, int port)
|
||||||
|
{
|
||||||
|
Version = version;
|
||||||
|
Address = address;
|
||||||
|
Port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Config FromDtsod(DtsodV23 d)
|
||||||
|
{
|
||||||
|
var cfg = new Config(d["version"], d["address"], d["port"]);
|
||||||
|
if (cfg.Version < ActualVersion)
|
||||||
|
throw new Exception($"config is obsolete (config v{cfg.Version} < program v{ActualVersion})");
|
||||||
|
if(cfg.Version > ActualVersion)
|
||||||
|
throw new Exception($"program is obsolete (config v{cfg.Version} > program v{ActualVersion})");
|
||||||
|
return cfg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DtsodV23 ToDtsod() =>
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
{ "version", Version },
|
||||||
|
{ "address", Address },
|
||||||
|
{ "port", Port }
|
||||||
|
};
|
||||||
|
|
||||||
|
public override string ToString() => ToDtsod().ToString()!;
|
||||||
|
}
|
||||||
16
Fluzm/Fluzm.csproj
Normal file
16
Fluzm/Fluzm.csproj
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
<ImplicitUsings>disable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="DTLib.Ben.Demystifier" Version="1.0.4" />
|
||||||
|
<PackageReference Include="DTLib.Dtsod" Version="1.3.0" />
|
||||||
|
<PackageReference Include="DTLib.Logging" Version="1.3.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
85
Fluzm/Program.cs
Normal file
85
Fluzm/Program.cs
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
global using System;
|
||||||
|
global using System.Collections.Generic;
|
||||||
|
global using System.Net;
|
||||||
|
global using System.Text;
|
||||||
|
global using System.Threading;
|
||||||
|
global using System.Threading.Tasks;
|
||||||
|
global using DTLib.Filesystem;
|
||||||
|
global using DTLib.Extensions;
|
||||||
|
using DTLib.Dtsod;
|
||||||
|
using DTLib.Logging;
|
||||||
|
|
||||||
|
namespace Fluzm;
|
||||||
|
|
||||||
|
internal static class Program
|
||||||
|
{
|
||||||
|
private static readonly IOPath configPath = "./config.dtsod";
|
||||||
|
private static CancellationTokenSource mainCancel = new();
|
||||||
|
private static ILogger logger = new ConsoleLogger();
|
||||||
|
private static Router router = new Router();
|
||||||
|
|
||||||
|
public static async Task Main(string[] args)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Console.InputEncoding = Encoding.UTF8;
|
||||||
|
Console.OutputEncoding = Encoding.UTF8;
|
||||||
|
Console.CancelKeyPress += (_, _) =>
|
||||||
|
{
|
||||||
|
logger.LogInfo("Main","stopping server...");
|
||||||
|
mainCancel.Cancel();
|
||||||
|
};
|
||||||
|
|
||||||
|
Config config;
|
||||||
|
if (!File.Exists(configPath))
|
||||||
|
{
|
||||||
|
logger.LogWarn("Main", "Config file not found.");
|
||||||
|
config = new Config();
|
||||||
|
File.WriteAllText(configPath, config.ToString());
|
||||||
|
logger.LogWarn("Main", $"Created default at {configPath}.");
|
||||||
|
}
|
||||||
|
else config = Config.FromDtsod(new DtsodV23(File.ReadAllText(configPath)));
|
||||||
|
|
||||||
|
string baseUrl = $"http://{config.Address}:{config.Port}/";
|
||||||
|
logger.LogInfo("Main", $"starting webserver at {baseUrl} ...");
|
||||||
|
var server = new HttpListener();
|
||||||
|
server.Prefixes.Add(baseUrl);
|
||||||
|
server.Start();
|
||||||
|
logger.LogInfo("Main", "server started");
|
||||||
|
long requestId = 0;
|
||||||
|
while (!mainCancel.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
await Task.Run(async () =>
|
||||||
|
{
|
||||||
|
var ctx = await server.GetContextAsync();
|
||||||
|
HandleRequestAsync(ctx, requestId);
|
||||||
|
}, mainCancel.Token);
|
||||||
|
requestId++;
|
||||||
|
}
|
||||||
|
|
||||||
|
server.Stop();
|
||||||
|
logger.LogInfo("Main", "server stopped");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
logger.LogError("Main", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async void HandleRequestAsync(HttpListenerContext ctx, long requestId)
|
||||||
|
{
|
||||||
|
await Task.Yield();
|
||||||
|
string logContext = "Request " + requestId;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
logger.LogInfo(logContext, $"{ctx.Request.HttpMethod} request for {ctx.Request.RawUrl} from {ctx.Request.RemoteEndPoint}");
|
||||||
|
if(router.TryResolve(ctx))
|
||||||
|
logger.LogInfo(logContext, "request handled");
|
||||||
|
else logger.LogInfo(logContext, "request rejected");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
logger.LogWarn(logContext, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
35
Fluzm/Router.cs
Normal file
35
Fluzm/Router.cs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
namespace Fluzm;
|
||||||
|
|
||||||
|
public class Router
|
||||||
|
{
|
||||||
|
private Dictionary<string, Func<HttpListenerContext, int>> routes = new();
|
||||||
|
private Func<HttpListenerContext, int> rejectDelegate;
|
||||||
|
|
||||||
|
public Router()
|
||||||
|
{
|
||||||
|
routes.Add("/", ctx =>
|
||||||
|
{
|
||||||
|
var buffer = "<html><body><h1>UwU</h1></body></html>".ToBytes();
|
||||||
|
ctx.Response.ContentLength64 = buffer.Length;
|
||||||
|
ctx.Response.OutputStream.Write(buffer);
|
||||||
|
ctx.Response.OutputStream.Flush();
|
||||||
|
return 200;
|
||||||
|
});
|
||||||
|
rejectDelegate = ctx =>
|
||||||
|
{
|
||||||
|
ctx.Response.ContentLength64 = 0;
|
||||||
|
return 500;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryResolve(HttpListenerContext ctx)
|
||||||
|
{
|
||||||
|
int status = routes.TryGetValue(ctx.Request.Url!.AbsolutePath, out var routeDelegate)
|
||||||
|
? routeDelegate(ctx)
|
||||||
|
: rejectDelegate(ctx);
|
||||||
|
ctx.Response.StatusCode = status;
|
||||||
|
ctx.Response.OutputStream.Flush();
|
||||||
|
ctx.Response.OutputStream.Close();
|
||||||
|
return status == 200;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user