Skip to content

Instantly share code, notes, and snippets.

@altbodhi
Created July 1, 2020 13:12
Show Gist options
  • Select an option

  • Save altbodhi/135e00f346045f6f519c02eb81a5cac3 to your computer and use it in GitHub Desktop.

Select an option

Save altbodhi/135e00f346045f6f519c02eb81a5cac3 to your computer and use it in GitHub Desktop.
nemerle http server
using System;
using System.Console;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Nemerle;
using Nemerle.Async;
def mimeTypes = [(".html", "text/html"), (".htm", "text/html"), (".txt", "text/plain"), (".gif", "image/gif"), (".jpg", "image/jpeg"), (".png", "image/png")];
def getMimeType(ext) {
match(mimeTypes.MapFiltered((k,_) => String.Compare(ext,k) == 0, (_, v) => v)) {
| v :: _ => v
| [] => "binary/octet" }
}
def root = ".\\wwwroot\\";
def port = 8181;
def defaultUrl = $"http://localhost:$port/index.html";
unless(Directory.Exists(root))
_ = Directory.CreateDirectory(root);
def Log(msg) {
WriteLine("{0}\t{1}",DateTime.Now, msg : object);
}
def ExtractValue(patt, inp) {
try {
Some(Regex.Match(inp, patt).Groups[1].Captures[0].Value)
} catch { | _ => None() }
}
def handleRequest(client : TcpClient) {
using (stream = client.GetStream()) {
def ou = StreamWriter(stream);
def rdr = StreamReader(stream);
def headers (lines) {
lines.Iter(ou.WriteLine);
ou.WriteLine("");
ou.Flush();
}
def notFound () { headers (["HTTP/1.0 404 Not Found"]) }
def request = rdr.ReadLine();
Log($"$(client.Client.RemoteEndPoint)\t $request");
match(request) {
| "GET / HTTP/1.0" | "GET / HTTP/1.1" => headers (["HTTP/1.0 302 Found", $"Location: $defaultUrl"]);
| _ => {
match(ExtractValue("GET /(.*?) HTTP/1\\.[01]$", request)) {
| Some(fileName) => {
def fname = Path.Combine(root, fileName);
def mimeType = getMimeType(Path.GetExtension(fname));
if(!File.Exists(fname)) {
Log($"! request $fname not found");
notFound(); }
else { def content = File.ReadAllBytes(fname);
headers(["HTTP/1.0 200 OK", $"Content-Length: $(content.Length)", $"Content-Type: $mimeType" ]);
stream.Write(content, 0, content.Length)}
}
| None() => notFound()
}
}
}
}
}
def server( port = 8181) {
def socket = TcpListener(IPAddress.Any, port);
socket.Start();
WriteLine($"Server Start and Listen port = $port...");
while(true) {
using(client = socket.AcceptTcpClient()) {
handleRequest(client) }
}
}
server(port);
_ = ReadLine();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment