360 likes | 411 Views
The Functional Web. Ryan Riley. Logos Bible Software Community for F# F# MVP OSS: FSharpx , Fracture, Frank @ panesofglass. Outline. The State of HTTP on .NET Composition Patterns in HTTP Identifying Problems Examining a Solution. The State of HTTP on .NET. Current Options. http.sys
E N D
Ryan Riley • Logos Bible Software • Community for F# • F# MVP • OSS: FSharpx, Fracture, Frank • @panesofglass
Outline • The State of HTTP on .NET • Composition Patterns in HTTP • Identifying Problems • Examining a Solution
Current Options • http.sys • HttpListener • IIS (IHttpModule & IHttpHandler) • Web Forms • MVC • WCF HTTP & Data Services
Future Options • System.Net.Http (BETA) • .NET 4.5 • Available on NuGet • ASP.NET Web API (BETA) • Builds on System.Net.Http • Integrated with MVC 4
OSS Options Servers FubuMVC MonoRail NancyFx OpenRasta OWIN/Gate ServiceStack.NET WebSharper … and many more! Firefly (OWIN) Fracture (F#) Kayak (OWIN) Manos de Mono Mono XSP Frameworks
Component Parts • Request/Response Lines • Methods, URIs, Status Codes • Headers • General, Request, Response, Content • Resources • Representations • Hypermedia
Simplest HTTP Application HttpRequestMessage -> HttpResponseMessage
Resources GET /item/1 + POST /item/1 + PUT /item/1 + OPTIONS /item/1 = Resource at / with GET, POST, PUT, & OPTIONS
HTTP Applications / + /items + /item/{itemId} + /help = Typical HTTP “application”
Content Negotiation Server Supports application/xml;q=0.9 application/json;q=0.8 text/plain;q=0.5 application/json text/plain text/html Client Accepts application/json
HttpListener • Low-level • Defines the signature for a single application only • HttpListenerContext provides a singleton; no chance to intercept and chain behavior • Routing requests requires custom handling; typically by using imperative if-then-else • No means of chaining or composing multiple listeners
HttpListener HttpListener.Start ("http://localhost:8082/", (fun (request, response) -> async { match request.Url.LocalPath with | "/post" -> // Send message to the chat room room.SendMessage(request.InputString) response.Reply("OK") | "/chat" -> // Get messages from the chat room (asynchronously!) let! text = room.AsyncGetContent() response.Reply(text) | s -> // Handle an ordinary file request let file = root + (if s = "/" then "chat.html" else s.ToLower()) if File.Exists(file) then let typ = contentTypes.[Path.GetExtension(file)] response.Reply(typ, File.ReadAllBytes(file)) else response.Reply(sprintf "File not found: %s" file) }), cts.Token)
IHttpModule & IHttpHandler • Low-level • HttpContext has the same problems as HttpListenerContext • IHttpHandler could represent a Resource, but method mapping is imperative • IHttpModule provides a middleware layer for routing or hosting multiple IHttpHandlers • System.Web.Routing surfaces the routing component
IHttpModule & IHttpHandler interface IHttpModule { void Dispose(); void Init(HttpApplication context); } interface IHttpHandler { bool IsReusable { get; } void ProcessRequest(HttpContext context); }
ASP.NET Web Forms • HTML composition via MasterPages, Pages, and Controls • Suffers many problems associated with IHttpModule and IHttpHandler • Evented model allows for interception • No built-in support for other representations • Pages loosely correlate to Resources • Application composition and routing by file path
ASP.NET MVC • Suffers many problems associated with IHttpModule and IHttpHandler • Primarily HTML generation but allows for better HTTP control • Built-in support for handling Ajax requests • ActionFilters allow for behavior composition at different points: Authorize, ActionExecuting, ActionExecuted, ResultExecuting, ResultExecuted
ASP.NET MVC, cont. • Content Negotiation is still very manual • ViewEngines and Serializers can be made to render various representations • ViewEngines offer representation composition • Controllers ~ Resources, but not quite • Areas and Routing allow for Nested Resources, to a degree
Problem Summary • Have: • Limited interception for cross-cutting concerns • Representation composition • Do not have: • No easy resource composition • No built-in content negotiation
Composition for Conneg • Rendering • Imperative if-then-else • Serializers • Location • Within the specific method handler (common for imperative) • Top-level (common for serializers) • Why not both?
Nested Resources • Imperative if-then-else • Routing • MVC Areas offer another level • What about more than one level? • Rails – problem with deep URIs • System.Web.Routing does everything at the top-level, so tracking deeper resource trees is difficult.
Function Composition • Functional programming offers solutions to these problems • Filter • Map • Reduce
Frank • F# DSL using System.Net.Http • Headers composition • Follows the natural composition of HTTP • Frank Resources == HTTP Resources • Define your own conventions!
Simplest HTTP Frank Application HttpRequestMessage -> HttpResponseMessage HttpRequestMessage -> Async<HttpResponseMessage>
Define a Method Handler // handler let echo request = async { let! body = request.Content.AsyncReadAsString() return HttpResponseMessage.ReplyTo(request, body) } // method handler get echo
Define a Resource let helloworld request = async { … } let echo request = async { … } let resource = route “/” (get helloworld <|> post echo)
Define an Application let todoListResource = route “/” (get todoList <|> …) let todoItemResource = route “/item/{1}” (put …) let app = merge [ todoListResource; todoItemResource]
Leverage Conneg valnegotiateMediaType = formatters -> HttpRequestMessage -> string -> Async<HttpResponseMessage> let echo = negotiateMediaType formatters <| fun request -> request.Content.AsyncReadAsString())
WebSharper • One language for both client and server • Can leverage to cleanly separate parts • Use WebSharper to generate code-on-demand to send to the client • Plays well with existing tools
Resources • ASP.NET Web Forms in F# • ASP.NET MVC in F# • Figment DSL for MVC • Frank DSL for Web API • WebSharper • Pit FW
Thank you! • Please rate this talk: http://speakerrate.com/talks/9293-the-functional-web