Skip to content

Instantly share code, notes, and snippets.

@define-private-public
Last active April 9, 2024 08:38
Show Gist options
  • Save define-private-public/d05bc52dd0bed1c4699d49e2737e80e7 to your computer and use it in GitHub Desktop.
Save define-private-public/d05bc52dd0bed1c4699d49e2737e80e7 to your computer and use it in GitHub Desktop.
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();
}
}
}
@AlexanderHS
Copy link

Been fooling around with this and noticed some unanswered questions above. Can only tell you what worked for me.

"I want to send a json string to the http server. How can I get the message from the request?"

I went with something like:

string payload = GetRequestPostData(ctx.Request);
Where you define that function like:

string GetRequestPostData(HttpListenerRequest request)
{
    if (!request.HasEntityBody)
    {
        return null;
    }
    using (System.IO.Stream body = request.InputStream)
    {
        using (var reader = new System.IO.StreamReader(body, request.ContentEncoding))
        {
            return reader.ReadToEnd();
        }
    }
}

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?

change localhost to something like + or *
e.g.
string url = $"http://+:8000/";
Your OS might complain about permissions though.

If so you can try something like: "netsh http add urlacl url=http://+:8000/ user=your_username_here"

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