using System;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
using Uwaa.HTTP.Websockets;
using Uwaa.HTTP.Routing;
namespace Uwaa.HTTP.Example;
static class Program
{
static void Main(string[] args)
{
Console.WriteLine("Loading test certificate");
X509Certificate cert = X509Certificate.CreateFromCertFile("certs/localhost.pfx");
Console.WriteLine("Preparing listeners");
Router router = CreateRouter();
HttpServer httpServer = new HttpServer(80, null, router);
HttpServer httpsServer = new HttpServer(443, cert, router);
httpServer.OnConnectionBegin += LogConnect;
httpServer.OnConnectionEnd += LogDisconnect;
httpsServer.OnConnectionBegin += LogConnect;
httpsServer.OnConnectionEnd += LogDisconnect;
httpServer.Start();
httpsServer.Start();
Console.WriteLine($"Ready on ports {httpServer.Port} and {httpsServer.Port}");
TestClient();
Task.Delay(-1).Wait();
}
///
/// Generates the URL router for the HTTP server.
///
static Router CreateRouter()
{
//The order here matters
Router subpath = new Router();
subpath.Add("foo", new StaticEndpoint(HttpResponse.OK("A \"foo\" example sub page")));
subpath.Add("bar", new StaticEndpoint(HttpResponse.OK("A \"bar\" example sub page")));
Router router = new Router();
router.Add(LogRequest);
router.Add(new CORS());
router.Add("custom", new CustomRoute());
router.Add("subpath", subpath);
router.Add(new FileEndpoint("www-static") { Index = false });
router.Add(new FileEndpoint("www-dynamic") { Index = false });
router.Add("", Root);
router.Add(new StaticEndpoint(HttpResponse.NotFound("File not found")));
return router;
}
///
/// Example HTTP client request.
///
static async void TestClient()
{
Console.WriteLine("Connecting");
//Make request
HttpRequest req = new HttpRequest(HttpMethod.GET, "/test.txt");
req.Fields.UserAgent = "test (Uwaa.HTTP)";
req.Fields.Connection = ConnectionType.Close;
//Send, get response
HttpResponse res = await HttpClient.Request("localhost", true, req);
string resText = res.Content?.AsText ?? "null";
Console.WriteLine("Got response: " + resText);
}
///
/// Logs a new connection to the console.
///
static void LogConnect(TcpClient client)
{
Console.WriteLine($"{client.Client.RemoteEndPoint} connected");
}
///
/// Logs a disconnection to the console.
///
static void LogDisconnect(IPEndPoint endpoint)
{
Console.WriteLine($"{endpoint} disconnected");
}
///
/// Logs a request to the console.
///
static HttpResponse? LogRequest(HttpRequest req, HttpClientInfo info)
{
Console.WriteLine($"{info.Endpoint.Address}: {req.Method} {req.Path}");
return null;
}
///
/// Root endpoint: /
///
static async Task Root(HttpRequest req, HttpClientInfo info)
{
if (req.IsWebsocket)
return Websocket(req, info);
byte[] indexFile = await File.ReadAllBytesAsync("www-static/index.html");
HttpContent html = new HttpContent(new MIMEType("text", "html"), indexFile);
return HttpResponse.OK(html);
}
///
/// Websocket endpoint
///
static HttpResponse? Websocket(HttpRequest req, HttpClientInfo info)
{
return req.UpgradeToWebsocket(HandleWebsocket, "test");
}
static async Task HandleWebsocket(Websocket ws)
{
TimeSpan timeout = TimeSpan.FromMinutes(1);
DataFrame payload = await ws.Read().WaitAsync(timeout);
if (payload.Opcode != WSOpcode.Close)
{
string result = payload.AsString();
await ws.Write($"Echoing message: \"{result}\"").WaitAsync(timeout);
}
return CloseStatus.NormalClosure;
}
///
/// Custom route: /custom/{param1}/{param2}
///
class CustomRoute : RouterBase
{
public override HttpMethod Method => HttpMethod.GET;
public override int Arguments => 2;
protected override Task GetResponseInner(HttpRequest req, HttpClientInfo info, ArraySegment path)
{
string param1 = path[0];
string param2 = path[1];
return Task.FromResult(HttpResponse.OK($"Variable 1: {param1}\nVariable 2: {param2}"));
}
}
}