Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A Simple HTTP server in C#
// Filename: HttpServer.cs
// Author: Benjamin N. Summerton <define-private-public>
// License: Unlicense (http://unlicense.org/)
using System;
using System.IO;
using System.Text;
using System.Net;
using System.Threading.Tasks;
namespace HttpListenerExample
{
class HttpServer
{
public static HttpListener listener;
public static string url = "http://localhost:8000/";
public static int pageViews = 0;
public static int requestCount = 0;
public static string pageData =
"<!DOCTYPE>" +
"<html>" +
" <head>" +
" <title>HttpListener Example</title>" +
" </head>" +
" <body>" +
" <p>Page Views: {0}</p>" +
" <form method=\"post\" action=\"shutdown\">" +
" <input type=\"submit\" value=\"Shutdown\" {1}>" +
" </form>" +
" </body>" +
"</html>";
public static async Task HandleIncomingConnections()
{
bool runServer = true;
// While a user hasn't visited the `shutdown` url, keep on handling requests
while (runServer)
{
// Will wait here until we hear from a connection
HttpListenerContext ctx = await listener.GetContextAsync();
// Peel out the requests and response objects
HttpListenerRequest req = ctx.Request;
HttpListenerResponse resp = ctx.Response;
// Print out some info about the request
Console.WriteLine("Request #: {0}", ++requestCount);
Console.WriteLine(req.Url.ToString());
Console.WriteLine(req.HttpMethod);
Console.WriteLine(req.UserHostName);
Console.WriteLine(req.UserAgent);
Console.WriteLine();
// If `shutdown` url requested w/ POST, then shutdown the server after serving the page
if ((req.HttpMethod == "POST") && (req.Url.AbsolutePath == "/shutdown"))
{
Console.WriteLine("Shutdown requested");
runServer = false;
}
// Make sure we don't increment the page views counter if `favicon.ico` is requested
if (req.Url.AbsolutePath != "/favicon.ico")
pageViews += 1;
// Write the response info
string disableSubmit = !runServer ? "disabled" : "";
byte[] data = Encoding.UTF8.GetBytes(String.Format(pageData, pageViews, disableSubmit));
resp.ContentType = "text/html";
resp.ContentEncoding = Encoding.UTF8;
resp.ContentLength64 = data.LongLength;
// Write out to the response stream (asynchronously), then close it
await resp.OutputStream.WriteAsync(data, 0, data.Length);
resp.Close();
}
}
public static void Main(string[] args)
{
// Create a Http server and start listening for incoming connections
listener = new HttpListener();
listener.Prefixes.Add(url);
listener.Start();
Console.WriteLine("Listening for connections on {0}", url);
// Handle requests
Task listenTask = HandleIncomingConnections();
listenTask.GetAwaiter().GetResult();
// Close the listener
listener.Close();
}
}
}
@nikola354

This comment has been minimized.

Copy link

@nikola354 nikola354 commented Dec 19, 2019

Briliant solution! One question: I want to send a json string to the http server. How can I get the message from the request?

@define-private-public

This comment has been minimized.

Copy link
Owner Author

@define-private-public define-private-public commented Dec 19, 2019

I'm not quite sure myself, but my guess would be to check the HttpListenerRequest object that's received by the server: https://docs.microsoft.com/en-us/dotnet/api/system.net.httplistenerrequest?view=netframework-4.8

@define-private-public

This comment has been minimized.

Copy link
Owner Author

@define-private-public define-private-public commented Dec 19, 2019

Reading the docs further, I think it might be the request's InputStream you need to read: https://docs.microsoft.com/en-us/dotnet/api/system.net.httplistenerrequest.inputstream?view=netframework-4.8#examples

@nikola354

This comment has been minimized.

Copy link

@nikola354 nikola354 commented Dec 21, 2019

Thanks!

@hazelForet

This comment has been minimized.

Copy link

@hazelForet hazelForet commented May 29, 2020

Thanks! I have one issue with redirecting https calls into http. for example if the client requested https://myserver/login will automatically redirected to http://myserver/login

@define-private-public

This comment has been minimized.

Copy link
Owner Author

@define-private-public define-private-public commented May 29, 2020

Thanks! I have one issue with redirecting https calls into http. for example if the client requested https://myserver/login will automatically redirected to http://myserver/login

https requires SSL certs and whatnot, and that's always a pain to setup and use. This is meant for something to run locally on a computer, not an externally facing thing, so I don't think that https is something to worry about for this use case.

@Elias-Traunbauer

This comment has been minimized.

Copy link

@Elias-Traunbauer Elias-Traunbauer commented Sep 24, 2020

SSL Encryption

How can I get this Server to work with https://myIp:myPort/ ?

@tebeco

This comment has been minimized.

Copy link

@tebeco tebeco commented Jan 22, 2021

How can I get this Server to work with https://myIp:myPort/ ?

you could just use Kestrel with AspNetCore you'll have a proper webserver (TLS is part of it)

md foo
cd foo
git init
dotnet new gitignore
dotnet new sln
dotnet new web -n TheNameHere
dotnet sln add ./TheNameHere
git add .
git commit -m "I now have a proper http server with TLS enabled and https redirection setup"

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/?view=aspnetcore-5.0&tabs=linux

@ambozz

This comment has been minimized.

Copy link

@ambozz ambozz commented Feb 19, 2021

Good solution, but it doesn't work with other Networks on the same Network for example a Phone.
I tried changing "url" to the local IP Address of the Machine Running the code, but this doesn't work for neither my Phone or my PC.
Does anyone have a Solution to this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment