7 people like it.

Simple HTTP Server

Simple HTTP server, runs on .Net Core, .Net or Mono, and serves GET requests via a handler. The example given serves up static content from a specified directory.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
46: 
47: 
open System
open System.IO
open System.Net
open System.Net.Sockets

let acceptClient (client:TcpClient) handler = async {
   use stream = client.GetStream()
   use reader = new StreamReader(stream)
   let header = reader.ReadLine()
   if not (String.IsNullOrEmpty(header)) then
      use writer = new StreamWriter(stream)
      handler (header, writer)
      writer.Flush()
   }

let startServer (address, port) handler =
   let ip = IPAddress.Parse(address)
   let listener = Sockets.TcpListener(ip, port)
   listener.Start() 
   async { 
      while true do 
         let! client = listener.AcceptTcpClientAsync() |> Async.AwaitTask
         acceptClient client handler |> Async.Start
   }
   |> Async.Start

type StreamWriter with
   member writer.BinaryWrite(bytes:byte[]) =
      let writer = new BinaryWriter(writer.BaseStream)
      writer.Write(bytes)

let staticContentHandler root (header:string, response:StreamWriter) =
   let parts = header.Split(' ')
   let resource = parts.[1]
   let path = Path.Combine(root, resource.TrimStart('/').TrimStart('\\'))
   if File.Exists(path) then
      response.Write("HTTP/1.1 200 OK\r\n\r\n")
      if resource.EndsWith(".png") then
         let bytes = File.ReadAllBytes(path)
         response.BinaryWrite(bytes) 
      else
         let text = File.ReadAllText(path)
         response.Write(text)
   else
      response.Write("HTTP/1.1 404 Not found\r\n\r\n" + resource + " not found.")

startServer("127.0.0.1", 8080) (staticContentHandler @"C:\mynetpub")
namespace System
namespace System.IO
namespace System.Net
namespace System.Net.Sockets
val acceptClient : client:TcpClient -> handler:(string * StreamWriter -> unit) -> Async<unit>

Full name: Script.acceptClient
val client : TcpClient
Multiple items
type TcpClient =
  new : unit -> TcpClient + 3 overloads
  member Available : int
  member BeginConnect : host:string * port:int * requestCallback:AsyncCallback * state:obj -> IAsyncResult + 2 overloads
  member Client : Socket with get, set
  member Close : unit -> unit
  member Connect : remoteEP:IPEndPoint -> unit + 3 overloads
  member Connected : bool
  member EndConnect : asyncResult:IAsyncResult -> unit
  member ExclusiveAddressUse : bool with get, set
  member GetStream : unit -> NetworkStream
  ...

Full name: System.Net.Sockets.TcpClient

--------------------
TcpClient() : unit
TcpClient(localEP: IPEndPoint) : unit
TcpClient(family: AddressFamily) : unit
TcpClient(hostname: string, port: int) : unit
val handler : (string * StreamWriter -> unit)
val async : AsyncBuilder

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.async
val stream : NetworkStream
TcpClient.GetStream() : NetworkStream
val reader : StreamReader
Multiple items
type StreamReader =
  inherit TextReader
  new : stream:Stream -> StreamReader + 9 overloads
  member BaseStream : Stream
  member Close : unit -> unit
  member CurrentEncoding : Encoding
  member DiscardBufferedData : unit -> unit
  member EndOfStream : bool
  member Peek : unit -> int
  member Read : unit -> int + 1 overload
  member ReadLine : unit -> string
  member ReadToEnd : unit -> string
  ...

Full name: System.IO.StreamReader

--------------------
StreamReader(stream: Stream) : unit
StreamReader(path: string) : unit
StreamReader(stream: Stream, detectEncodingFromByteOrderMarks: bool) : unit
StreamReader(stream: Stream, encoding: Text.Encoding) : unit
StreamReader(path: string, detectEncodingFromByteOrderMarks: bool) : unit
StreamReader(path: string, encoding: Text.Encoding) : unit
StreamReader(stream: Stream, encoding: Text.Encoding, detectEncodingFromByteOrderMarks: bool) : unit
StreamReader(path: string, encoding: Text.Encoding, detectEncodingFromByteOrderMarks: bool) : unit
StreamReader(stream: Stream, encoding: Text.Encoding, detectEncodingFromByteOrderMarks: bool, bufferSize: int) : unit
StreamReader(path: string, encoding: Text.Encoding, detectEncodingFromByteOrderMarks: bool, bufferSize: int) : unit
val header : string
StreamReader.ReadLine() : string
val not : value:bool -> bool

Full name: Microsoft.FSharp.Core.Operators.not
Multiple items
type String =
  new : value:char -> string + 7 overloads
  member Chars : int -> char
  member Clone : unit -> obj
  member CompareTo : value:obj -> int + 1 overload
  member Contains : value:string -> bool
  member CopyTo : sourceIndex:int * destination:char[] * destinationIndex:int * count:int -> unit
  member EndsWith : value:string -> bool + 2 overloads
  member Equals : obj:obj -> bool + 2 overloads
  member GetEnumerator : unit -> CharEnumerator
  member GetHashCode : unit -> int
  ...

Full name: System.String

--------------------
String(value: nativeptr<char>) : unit
String(value: nativeptr<sbyte>) : unit
String(value: char []) : unit
String(c: char, count: int) : unit
String(value: nativeptr<char>, startIndex: int, length: int) : unit
String(value: nativeptr<sbyte>, startIndex: int, length: int) : unit
String(value: char [], startIndex: int, length: int) : unit
String(value: nativeptr<sbyte>, startIndex: int, length: int, enc: Text.Encoding) : unit
String.IsNullOrEmpty(value: string) : bool
val writer : StreamWriter
Multiple items
type StreamWriter =
  inherit TextWriter
  new : stream:Stream -> StreamWriter + 6 overloads
  member AutoFlush : bool with get, set
  member BaseStream : Stream
  member Close : unit -> unit
  member Encoding : Encoding
  member Flush : unit -> unit
  member Write : value:char -> unit + 3 overloads
  static val Null : StreamWriter

Full name: System.IO.StreamWriter

--------------------
StreamWriter(stream: Stream) : unit
StreamWriter(path: string) : unit
StreamWriter(stream: Stream, encoding: Text.Encoding) : unit
StreamWriter(path: string, append: bool) : unit
StreamWriter(stream: Stream, encoding: Text.Encoding, bufferSize: int) : unit
StreamWriter(path: string, append: bool, encoding: Text.Encoding) : unit
StreamWriter(path: string, append: bool, encoding: Text.Encoding, bufferSize: int) : unit
StreamWriter.Flush() : unit
val startServer : address:string * port:int -> handler:(string * StreamWriter -> unit) -> unit

Full name: Script.startServer
val address : string
val port : int
val ip : IPAddress
Multiple items
type IPAddress =
  new : newAddress:int64 -> IPAddress + 2 overloads
  member Address : int64 with get, set
  member AddressFamily : AddressFamily
  member Equals : comparand:obj -> bool
  member GetAddressBytes : unit -> byte[]
  member GetHashCode : unit -> int
  member IsIPv6LinkLocal : bool
  member IsIPv6Multicast : bool
  member IsIPv6SiteLocal : bool
  member IsIPv6Teredo : bool
  ...

Full name: System.Net.IPAddress

--------------------
IPAddress(newAddress: int64) : unit
IPAddress(address: byte []) : unit
IPAddress(address: byte [], scopeid: int64) : unit
IPAddress.Parse(ipString: string) : IPAddress
val listener : TcpListener
Multiple items
type TcpListener =
  new : localEP:IPEndPoint -> TcpListener + 2 overloads
  member AcceptSocket : unit -> Socket
  member AcceptTcpClient : unit -> TcpClient
  member AllowNatTraversal : allowed:bool -> unit
  member BeginAcceptSocket : callback:AsyncCallback * state:obj -> IAsyncResult
  member BeginAcceptTcpClient : callback:AsyncCallback * state:obj -> IAsyncResult
  member EndAcceptSocket : asyncResult:IAsyncResult -> Socket
  member EndAcceptTcpClient : asyncResult:IAsyncResult -> TcpClient
  member ExclusiveAddressUse : bool with get, set
  member LocalEndpoint : EndPoint
  ...

Full name: System.Net.Sockets.TcpListener

--------------------
TcpListener(localEP: IPEndPoint) : unit
TcpListener(localaddr: IPAddress, port: int) : unit
TcpListener.Start() : unit
TcpListener.Start(backlog: int) : unit
Multiple items
type Async
static member AsBeginEnd : computation:('Arg -> Async<'T>) -> ('Arg * AsyncCallback * obj -> IAsyncResult) * (IAsyncResult -> 'T) * (IAsyncResult -> unit)
static member AwaitEvent : event:IEvent<'Del,'T> * ?cancelAction:(unit -> unit) -> Async<'T> (requires delegate and 'Del :> Delegate)
static member AwaitIAsyncResult : iar:IAsyncResult * ?millisecondsTimeout:int -> Async<bool>
static member AwaitTask : task:Task -> Async<unit>
static member AwaitTask : task:Task<'T> -> Async<'T>
static member AwaitWaitHandle : waitHandle:WaitHandle * ?millisecondsTimeout:int -> Async<bool>
static member CancelDefaultToken : unit -> unit
static member Catch : computation:Async<'T> -> Async<Choice<'T,exn>>
static member FromBeginEnd : beginAction:(AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg:'Arg1 * beginAction:('Arg1 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * beginAction:('Arg1 * 'Arg2 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * arg3:'Arg3 * beginAction:('Arg1 * 'Arg2 * 'Arg3 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromContinuations : callback:(('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) -> unit) -> Async<'T>
static member Ignore : computation:Async<'T> -> Async<unit>
static member OnCancel : interruption:(unit -> unit) -> Async<IDisposable>
static member Parallel : computations:seq<Async<'T>> -> Async<'T []>
static member RunSynchronously : computation:Async<'T> * ?timeout:int * ?cancellationToken:CancellationToken -> 'T
static member Sleep : millisecondsDueTime:int -> Async<unit>
static member Start : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
static member StartAsTask : computation:Async<'T> * ?taskCreationOptions:TaskCreationOptions * ?cancellationToken:CancellationToken -> Task<'T>
static member StartChild : computation:Async<'T> * ?millisecondsTimeout:int -> Async<Async<'T>>
static member StartChildAsTask : computation:Async<'T> * ?taskCreationOptions:TaskCreationOptions -> Async<Task<'T>>
static member StartImmediate : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
static member StartWithContinuations : computation:Async<'T> * continuation:('T -> unit) * exceptionContinuation:(exn -> unit) * cancellationContinuation:(OperationCanceledException -> unit) * ?cancellationToken:CancellationToken -> unit
static member SwitchToContext : syncContext:SynchronizationContext -> Async<unit>
static member SwitchToNewThread : unit -> Async<unit>
static member SwitchToThreadPool : unit -> Async<unit>
static member TryCancelled : computation:Async<'T> * compensation:(OperationCanceledException -> unit) -> Async<'T>
static member CancellationToken : Async<CancellationToken>
static member DefaultCancellationToken : CancellationToken

Full name: Microsoft.FSharp.Control.Async

--------------------
type Async<'T>

Full name: Microsoft.FSharp.Control.Async<_>
static member Async.AwaitTask : task:Threading.Tasks.Task -> Async<unit>
static member Async.AwaitTask : task:Threading.Tasks.Task<'T> -> Async<'T>
static member Async.Start : computation:Async<unit> * ?cancellationToken:Threading.CancellationToken -> unit
member StreamWriter.BinaryWrite : bytes:byte [] -> unit

Full name: Script.BinaryWrite
val bytes : byte []
Multiple items
val byte : value:'T -> byte (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.byte

--------------------
type byte = Byte

Full name: Microsoft.FSharp.Core.byte
val writer : BinaryWriter
Multiple items
type BinaryWriter =
  new : output:Stream -> BinaryWriter + 1 overload
  member BaseStream : Stream
  member Close : unit -> unit
  member Dispose : unit -> unit
  member Flush : unit -> unit
  member Seek : offset:int * origin:SeekOrigin -> int64
  member Write : value:bool -> unit + 17 overloads
  static val Null : BinaryWriter

Full name: System.IO.BinaryWriter

--------------------
BinaryWriter(output: Stream) : unit
BinaryWriter(output: Stream, encoding: Text.Encoding) : unit
property BinaryWriter.BaseStream: Stream
BinaryWriter.Write(value: string) : unit
   (+0 other overloads)
BinaryWriter.Write(value: float32) : unit
   (+0 other overloads)
BinaryWriter.Write(value: uint64) : unit
   (+0 other overloads)
BinaryWriter.Write(value: int64) : unit
   (+0 other overloads)
BinaryWriter.Write(value: uint32) : unit
   (+0 other overloads)
BinaryWriter.Write(value: int) : unit
   (+0 other overloads)
BinaryWriter.Write(value: uint16) : unit
   (+0 other overloads)
BinaryWriter.Write(value: int16) : unit
   (+0 other overloads)
BinaryWriter.Write(value: decimal) : unit
   (+0 other overloads)
BinaryWriter.Write(value: float) : unit
   (+0 other overloads)
val staticContentHandler : root:string -> header:string * response:StreamWriter -> unit

Full name: Script.staticContentHandler
val root : string
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = String

Full name: Microsoft.FSharp.Core.string
val response : StreamWriter
val parts : string []
String.Split([<ParamArray>] separator: char []) : string []
String.Split(separator: string [], options: StringSplitOptions) : string []
String.Split(separator: char [], options: StringSplitOptions) : string []
String.Split(separator: char [], count: int) : string []
String.Split(separator: string [], count: int, options: StringSplitOptions) : string []
String.Split(separator: char [], count: int, options: StringSplitOptions) : string []
val resource : string
val path : string
type Path =
  static val DirectorySeparatorChar : char
  static val AltDirectorySeparatorChar : char
  static val VolumeSeparatorChar : char
  static val InvalidPathChars : char[]
  static val PathSeparator : char
  static member ChangeExtension : path:string * extension:string -> string
  static member Combine : [<ParamArray>] paths:string[] -> string + 3 overloads
  static member GetDirectoryName : path:string -> string
  static member GetExtension : path:string -> string
  static member GetFileName : path:string -> string
  ...

Full name: System.IO.Path
Path.Combine([<ParamArray>] paths: string []) : string
Path.Combine(path1: string, path2: string) : string
Path.Combine(path1: string, path2: string, path3: string) : string
Path.Combine(path1: string, path2: string, path3: string, path4: string) : string
String.TrimStart([<ParamArray>] trimChars: char []) : string
type File =
  static member AppendAllLines : path:string * contents:IEnumerable<string> -> unit + 1 overload
  static member AppendAllText : path:string * contents:string -> unit + 1 overload
  static member AppendText : path:string -> StreamWriter
  static member Copy : sourceFileName:string * destFileName:string -> unit + 1 overload
  static member Create : path:string -> FileStream + 3 overloads
  static member CreateText : path:string -> StreamWriter
  static member Decrypt : path:string -> unit
  static member Delete : path:string -> unit
  static member Encrypt : path:string -> unit
  static member Exists : path:string -> bool
  ...

Full name: System.IO.File
File.Exists(path: string) : bool
TextWriter.Write(value: obj) : unit
   (+0 other overloads)
TextWriter.Write(value: decimal) : unit
   (+0 other overloads)
TextWriter.Write(value: float) : unit
   (+0 other overloads)
TextWriter.Write(value: float32) : unit
   (+0 other overloads)
TextWriter.Write(value: uint64) : unit
   (+0 other overloads)
TextWriter.Write(value: int64) : unit
   (+0 other overloads)
TextWriter.Write(value: uint32) : unit
   (+0 other overloads)
TextWriter.Write(value: int) : unit
   (+0 other overloads)
TextWriter.Write(value: bool) : unit
   (+0 other overloads)
StreamWriter.Write(value: string) : unit
   (+0 other overloads)
String.EndsWith(value: string) : bool
String.EndsWith(value: string, comparisonType: StringComparison) : bool
String.EndsWith(value: string, ignoreCase: bool, culture: Globalization.CultureInfo) : bool
File.ReadAllBytes(path: string) : byte []
member StreamWriter.BinaryWrite : bytes:byte [] -> unit
val text : string
File.ReadAllText(path: string) : string
File.ReadAllText(path: string, encoding: Text.Encoding) : string
Next Version Raw view Test code New version

More information

Link:http://fssnip.net/7OR
Posted:8 years ago
Author:Phillip Trelford
Tags: http , server , web