1 people like it.
Like the snippet!
Simple HTTP server
Handle index better
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:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
|
namespace FSharp.Http
open System.IO
open System.Net
open System.Threading
open System.Text
// ----------------------------------------------------------------------------
// Simple web server hosting static files
// ----------------------------------------------------------------------------
[<AutoOpen>]
module HttpExtensions =
type System.Net.HttpListener with
member x.AsyncGetContext() =
Async.FromBeginEnd(x.BeginGetContext, x.EndGetContext)
type System.Net.HttpListenerRequest with
member request.InputString =
use sr = new StreamReader(request.InputStream)
sr.ReadToEnd()
type System.Net.HttpListenerResponse with
member response.Reply(s:string) =
let buffer = Encoding.UTF8.GetBytes(s)
response.ContentLength64 <- int64 buffer.Length
response.OutputStream.Write(buffer,0,buffer.Length)
response.OutputStream.Close()
member response.Reply(typ, buffer:byte[]) =
response.ContentLength64 <- int64 buffer.Length
response.ContentType <- typ
response.OutputStream.Write(buffer,0,buffer.Length)
response.OutputStream.Close()
/// Simple HTTP server
type HttpServer private (url, root) =
let contentTypes =
dict [ ".css", "text/css"; ".html", "text/html"; ".js", "text/javascript";
".png", "image/png"; ".jpg", "image/jpg"; ".gif", "image/gif" ]
let tokenSource = new CancellationTokenSource()
let agent = MailboxProcessor<HttpListenerContext>.Start((fun inbox -> async {
while true do
let! context = inbox.Receive()
try
let s = context.Request.Url.LocalPath
// Handle an ordinary file request
let file = root + (if s.EndsWith("/") then s + "index.html" else s)
let file =
if not (File.Exists(file)) && File.Exists(file + "/index.html") then file + "/index.html"
else file
if File.Exists(file) then
let ext = Path.GetExtension(file).ToLower()
let typ = contentTypes.[ext]
context.Response.Reply(typ, File.ReadAllBytes(file))
else
context.Response.Reply(sprintf "File not found: %s" file)
with e ->
context.Response.Reply(sprintf "Error processing request: %A" e) }), tokenSource.Token)
let server = async {
use listener = new HttpListener()
listener.Prefixes.Add(url)
listener.Start()
while true do
let! context = listener.AsyncGetContext()
agent.Post(context) }
do Async.Start(server, cancellationToken = tokenSource.Token)
/// Stops the HTTP server and releases the TCP connection
member x.Stop() = tokenSource.Cancel()
/// Starts new HTTP server on the specified URL. The specified
/// function represents computation running inside the agent.
static member Start(url, root) =
new HttpServer(url, root)
|
namespace Microsoft.FSharp
namespace System
namespace System.IO
namespace System.Net
namespace System.Threading
namespace System.Text
Multiple items
type AutoOpenAttribute =
inherit Attribute
new : unit -> AutoOpenAttribute
new : path:string -> AutoOpenAttribute
member Path : string
Full name: Microsoft.FSharp.Core.AutoOpenAttribute
--------------------
new : unit -> AutoOpenAttribute
new : path:string -> AutoOpenAttribute
Multiple items
type HttpListener =
new : unit -> HttpListener
member Abort : unit -> unit
member AuthenticationSchemeSelectorDelegate : AuthenticationSchemeSelector with get, set
member AuthenticationSchemes : AuthenticationSchemes with get, set
member BeginGetContext : callback:AsyncCallback * state:obj -> IAsyncResult
member Close : unit -> unit
member DefaultServiceNames : ServiceNameCollection
member EndGetContext : asyncResult:IAsyncResult -> HttpListenerContext
member ExtendedProtectionPolicy : ExtendedProtectionPolicy with get, set
member ExtendedProtectionSelectorDelegate : ExtendedProtectionSelector with get, set
...
nested type ExtendedProtectionSelector
Full name: System.Net.HttpListener
--------------------
HttpListener() : unit
val x : HttpListener
member HttpListener.AsyncGetContext : unit -> Async<HttpListenerContext>
Full name: FSharp.Http.HttpExtensions.AsyncGetContext
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<'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.FromBeginEnd : beginAction:(System.AsyncCallback * obj -> System.IAsyncResult) * endAction:(System.IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member Async.FromBeginEnd : arg:'Arg1 * beginAction:('Arg1 * System.AsyncCallback * obj -> System.IAsyncResult) * endAction:(System.IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member Async.FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * beginAction:('Arg1 * 'Arg2 * System.AsyncCallback * obj -> System.IAsyncResult) * endAction:(System.IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member Async.FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * arg3:'Arg3 * beginAction:('Arg1 * 'Arg2 * 'Arg3 * System.AsyncCallback * obj -> System.IAsyncResult) * endAction:(System.IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
HttpListener.BeginGetContext(callback: System.AsyncCallback, state: obj) : System.IAsyncResult
HttpListener.EndGetContext(asyncResult: System.IAsyncResult) : HttpListenerContext
type HttpListenerRequest =
member AcceptTypes : string[]
member BeginGetClientCertificate : requestCallback:AsyncCallback * state:obj -> IAsyncResult
member ClientCertificateError : int
member ContentEncoding : Encoding
member ContentLength64 : int64
member ContentType : string
member Cookies : CookieCollection
member EndGetClientCertificate : asyncResult:IAsyncResult -> X509Certificate2
member GetClientCertificate : unit -> X509Certificate2
member HasEntityBody : bool
...
Full name: System.Net.HttpListenerRequest
val request : HttpListenerRequest
member HttpListenerRequest.InputString : string
Full name: FSharp.Http.HttpExtensions.InputString
val sr : 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: Encoding) : unit
StreamReader(path: string, detectEncodingFromByteOrderMarks: bool) : unit
StreamReader(path: string, encoding: Encoding) : unit
StreamReader(stream: Stream, encoding: Encoding, detectEncodingFromByteOrderMarks: bool) : unit
StreamReader(path: string, encoding: Encoding, detectEncodingFromByteOrderMarks: bool) : unit
StreamReader(stream: Stream, encoding: Encoding, detectEncodingFromByteOrderMarks: bool, bufferSize: int) : unit
StreamReader(path: string, encoding: Encoding, detectEncodingFromByteOrderMarks: bool, bufferSize: int) : unit
property HttpListenerRequest.InputStream: Stream
StreamReader.ReadToEnd() : string
type HttpListenerResponse =
member Abort : unit -> unit
member AddHeader : name:string * value:string -> unit
member AppendCookie : cookie:Cookie -> unit
member AppendHeader : name:string * value:string -> unit
member Close : unit -> unit + 1 overload
member ContentEncoding : Encoding with get, set
member ContentLength64 : int64 with get, set
member ContentType : string with get, set
member Cookies : CookieCollection with get, set
member CopyFrom : templateResponse:HttpListenerResponse -> unit
...
Full name: System.Net.HttpListenerResponse
val response : HttpListenerResponse
member HttpListenerResponse.Reply : s:string -> unit
Full name: FSharp.Http.HttpExtensions.Reply
val s : string
Multiple items
val string : value:'T -> string
Full name: Microsoft.FSharp.Core.Operators.string
--------------------
type string = System.String
Full name: Microsoft.FSharp.Core.string
val buffer : byte []
type Encoding =
member BodyName : string
member Clone : unit -> obj
member CodePage : int
member DecoderFallback : DecoderFallback with get, set
member EncoderFallback : EncoderFallback with get, set
member EncodingName : string
member Equals : value:obj -> bool
member GetByteCount : chars:char[] -> int + 3 overloads
member GetBytes : chars:char[] -> byte[] + 5 overloads
member GetCharCount : bytes:byte[] -> int + 2 overloads
...
Full name: System.Text.Encoding
property Encoding.UTF8: Encoding
Encoding.GetBytes(s: string) : byte []
Encoding.GetBytes(chars: char []) : byte []
Encoding.GetBytes(chars: char [], index: int, count: int) : byte []
Encoding.GetBytes(chars: nativeptr<char>, charCount: int, bytes: nativeptr<byte>, byteCount: int) : int
Encoding.GetBytes(s: string, charIndex: int, charCount: int, bytes: byte [], byteIndex: int) : int
Encoding.GetBytes(chars: char [], charIndex: int, charCount: int, bytes: byte [], byteIndex: int) : int
property HttpListenerResponse.ContentLength64: int64
Multiple items
val int64 : value:'T -> int64 (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.int64
--------------------
type int64 = System.Int64
Full name: Microsoft.FSharp.Core.int64
--------------------
type int64<'Measure> = int64
Full name: Microsoft.FSharp.Core.int64<_>
property System.Array.Length: int
property HttpListenerResponse.OutputStream: Stream
Stream.Write(buffer: byte [], offset: int, count: int) : unit
Stream.Close() : unit
member HttpListenerResponse.Reply : typ:string * buffer:byte [] -> unit
Full name: FSharp.Http.HttpExtensions.Reply
val typ : string
Multiple items
val byte : value:'T -> byte (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.byte
--------------------
type byte = System.Byte
Full name: Microsoft.FSharp.Core.byte
property HttpListenerResponse.ContentType: string
Multiple items
type HttpServer =
private new : url:string * root:string -> HttpServer
member Stop : unit -> unit
static member Start : url:string * root:string -> HttpServer
Full name: FSharp.Http.HttpServer
Simple HTTP server
--------------------
private new : url:string * root:string -> HttpServer
val url : string
val root : string
val contentTypes : System.Collections.Generic.IDictionary<string,string>
val dict : keyValuePairs:seq<'Key * 'Value> -> System.Collections.Generic.IDictionary<'Key,'Value> (requires equality)
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.dict
val tokenSource : CancellationTokenSource
Multiple items
type CancellationTokenSource =
new : unit -> CancellationTokenSource
member Cancel : unit -> unit + 1 overload
member Dispose : unit -> unit
member IsCancellationRequested : bool
member Token : CancellationToken
static member CreateLinkedTokenSource : [<ParamArray>] tokens:CancellationToken[] -> CancellationTokenSource + 1 overload
Full name: System.Threading.CancellationTokenSource
--------------------
CancellationTokenSource() : unit
val agent : MailboxProcessor<HttpListenerContext>
Multiple items
type MailboxProcessor<'Msg> =
interface IDisposable
new : body:(MailboxProcessor<'Msg> -> Async<unit>) * ?cancellationToken:CancellationToken -> MailboxProcessor<'Msg>
member Post : message:'Msg -> unit
member PostAndAsyncReply : buildMessage:(AsyncReplyChannel<'Reply> -> 'Msg) * ?timeout:int -> Async<'Reply>
member PostAndReply : buildMessage:(AsyncReplyChannel<'Reply> -> 'Msg) * ?timeout:int -> 'Reply
member PostAndTryAsyncReply : buildMessage:(AsyncReplyChannel<'Reply> -> 'Msg) * ?timeout:int -> Async<'Reply option>
member Receive : ?timeout:int -> Async<'Msg>
member Scan : scanner:('Msg -> Async<'T> option) * ?timeout:int -> Async<'T>
member Start : unit -> unit
member TryPostAndReply : buildMessage:(AsyncReplyChannel<'Reply> -> 'Msg) * ?timeout:int -> 'Reply option
...
Full name: Microsoft.FSharp.Control.MailboxProcessor<_>
--------------------
new : body:(MailboxProcessor<'Msg> -> Async<unit>) * ?cancellationToken:CancellationToken -> MailboxProcessor<'Msg>
type HttpListenerContext =
member Request : HttpListenerRequest
member Response : HttpListenerResponse
member User : IPrincipal
Full name: System.Net.HttpListenerContext
val inbox : MailboxProcessor<HttpListenerContext>
val async : AsyncBuilder
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.async
val context : HttpListenerContext
member MailboxProcessor.Receive : ?timeout:int -> Async<'Msg>
property HttpListenerContext.Request: HttpListenerRequest
property HttpListenerRequest.Url: System.Uri
property System.Uri.LocalPath: string
val file : string
System.String.EndsWith(value: string) : bool
System.String.EndsWith(value: string, comparisonType: System.StringComparison) : bool
System.String.EndsWith(value: string, ignoreCase: bool, culture: System.Globalization.CultureInfo) : bool
val not : value:bool -> bool
Full name: Microsoft.FSharp.Core.Operators.not
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
val ext : 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.GetExtension(path: string) : string
property HttpListenerContext.Response: HttpListenerResponse
member HttpListenerResponse.Reply : s:string -> unit
member HttpListenerResponse.Reply : typ:string * buffer:byte [] -> unit
File.ReadAllBytes(path: string) : byte []
val sprintf : format:Printf.StringFormat<'T> -> 'T
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf
val e : exn
property CancellationTokenSource.Token: CancellationToken
val server : Async<unit>
val listener : HttpListener
property HttpListener.Prefixes: HttpListenerPrefixCollection
HttpListenerPrefixCollection.Add(uriPrefix: string) : unit
HttpListener.Start() : unit
member HttpListener.AsyncGetContext : unit -> Async<HttpListenerContext>
member MailboxProcessor.Post : message:'Msg -> unit
static member Async.Start : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
val x : HttpServer
member HttpServer.Stop : unit -> unit
Full name: FSharp.Http.HttpServer.Stop
Stops the HTTP server and releases the TCP connection
CancellationTokenSource.Cancel() : unit
CancellationTokenSource.Cancel(throwOnFirstException: bool) : unit
static member HttpServer.Start : url:string * root:string -> HttpServer
Full name: FSharp.Http.HttpServer.Start
Starts new HTTP server on the specified URL. The specified
function represents computation running inside the agent.
More information