Skip to content

Instantly share code, notes, and snippets.

@owskio
Last active November 3, 2015 19:19
Show Gist options
  • Save owskio/ba8968057e5f42116d3a to your computer and use it in GitHub Desktop.
Save owskio/ba8968057e5f42116d3a to your computer and use it in GitHub Desktop.
//Heavily modified from: https://www.branded3.com/blog/creating-a-simple-http-server-with-f
open System; open System.Text; open System.IO; open System.Net
//Eliminate .NET line noise
type HttpListenerResponse with
member me.Close = me.OutputStream.Close
member me.WriteAsync str = Encoding.ASCII.GetBytes(s=str) |> me.OutputStream.AsyncWrite
type Uri with
member me.RelativeTo host = Uri(host).MakeRelativeUri(me).OriginalString
let (/) a b = Path.Combine(a,b)
//Config
let root,host = @"C:\GitHub\Nancy","http://localhost:8888/"
//Init the listener in a closure, Return an async block which has its '>>='
//called for every request (it seems to me), yielding a 'context'
let listen =
let l = new HttpListener()
l.Prefixes.Add host
l.Start() //Called once upon definition of 'listen'
async { //Is accessed repeatedly, however
let b,e = l.BeginGetContext, l.EndGetContext
let! context = Async.FromBeginEnd(b, e)
return context.Request,context.Response
}
let loop requestHandler =
Async.Start <| async { //Non-blocking
while true do
let! request, response = listen //Get the context asynchronously
do! requestHandler(request,response) //Handle the context asynchronously
}
Console.ReadLine() |> ignore //Retain console for printfn
//Can be broken down further to reveal the usual String -> String
//development pattern of mapping request urls to response bodies
loop(fun(request,response) ->
async {
let relativePath = request.Url.RelativeTo host //Request routing
let file = root / relativePath //Request routing
printfn "REQUESTED: %A" file //Logging
response.StatusCode <- int HttpStatusCode.OK //Response packaging
response.ContentType <- "text/html" //Response packaging
do! if File.Exists file //Response handling
then File.ReadAllText file
else "File does not exist!"
|> response.WriteAsync
response.Close() //Resource management :-)
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment