This recipe shows how to create a simple asynchronous HTTP server in C#.
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
namespace AsyncHttpServerAndClient
{
internal static class Program
{
internal static void Main(string[] args)
{
MainAsync(args).GetAwaiter().GetResult();
}
private static async Task MainAsync(string[] args)
{
var tcs = new TaskCompletionSource<object>();
Console.CancelKeyPress += (sender, e) => { tcs.SetResult(null); };
var server = new AsyncHttpServer(portNumber: 1234);
var task = Task.Run(() => server.Start());
await Console.Out.WriteLineAsync("Listening on port 1234. Open http://localhost:1234 in your browser.");
await Console.Out.WriteLineAsync("Trying to connect:");
await Console.Out.WriteLineAsync();
await GetResponseAsync("http://localhost:1234");
await Console.Out.WriteLineAsync("Press Ctrl+C to stop the server...");
await tcs.Task;
await server.Stop();
}
private static async Task GetResponseAsync(string url)
{
using (var client = new HttpClient())
{
var responseMessage = await client.GetAsync(url);
var responseHeaders = responseMessage.Headers.ToString();
var response = await responseMessage.Content.ReadAsStringAsync();
Console.WriteLine("Response headers:");
Console.WriteLine(responseHeaders);
Console.WriteLine("Response body:");
Console.WriteLine(response);
Console.WriteLine();
}
}
private class AsyncHttpServer
{
private const string ResponseTemplate =
"<html>" +
"<head>" +
"<title>Test</title>" +
"</head>" +
"<body>" +
"<h2>Test page</h2>" +
"<h4>Today is: {0}</h4>" +
"</body>" +
"</html>";
private readonly HttpListener _listener;
public AsyncHttpServer(int portNumber)
{
_listener = new HttpListener();
_listener.Prefixes.Add(string.Format("http://+:{0}/", portNumber));
}
public async Task Start()
{
_listener.Start();
while (true)
{
var ctx = await _listener.GetContextAsync();
Console.Out.WriteLine("Client connected...");
Console.Out.WriteLine("Serving file: '{0}'", ctx.Request.Url);
ctx.Response.Headers.Add("content-type: text/html; charset=UTF-8");
ctx.Response.Headers.Add("x-content-type-options: nosniff");
ctx.Response.Headers.Add("x-xss-protection:1; mode=block");
ctx.Response.Headers.Add("x-frame-options:DENY");
ctx.Response.Headers.Add("cache-control:no-store, no-cache, must-revalidate");
ctx.Response.Headers.Add("pragma:no-cache");
ctx.Response.Headers.Add("Server", "jl");
var response = string.Format(ResponseTemplate, DateTime.Now);
using (var sw = new StreamWriter(ctx.Response.OutputStream))
{
await sw.WriteAsync(response);
await sw.FlushAsync();
}
}
}
public async Task Stop()
{
await Console.Out.WriteLineAsync(
"Stopping server...");
if (_listener.IsListening)
{
_listener.Stop();
_listener.Close();
}
}
}
}
}