A Sane Approach to Modern Web Application Development Adam Chlipala February 22, 2010 1 Web 1.0 “Application” Hello world! 2 Forms Name: Page Submit to URL “Bar” Trigger for URL “Bar” Handler blah This field is called “name.” Foo Submit Hello, Foo ! print (“Hello, “ + ENV[“name”] + “!”) 3 Database Access Page Name: '; DELETE FROM balance Foo WHERE name <> ' Submit SQL DB Handler Hello, Foo! Your balance is $1.23. query (“SELECT balance FROM customers WHERE name = '” + ENV[“name”] + “'”) 4 Saner Languages/Frameworks ● Links ● Ocsigen ● LINQ ● WebSharper ● OPA (“One-Pot Application”) ● ...? 5 Web 1.0 Components Users Table IsDisplay Y the password of user X? a login form here. Authentication Which user is this? What is user X's password? Login Cookie ? Main App Tell me the cookie contents, so that I can accidentally include them in a web page! 6 Web 2.0 Components Subtree of Dynamic Page Structure Write a contents new line to Save the to the the area. server. Writable Area Server-Side RPC Handler Which linesthe arecontents. there now? Restore ? Main App Let me mess with your part of the Let me call the RPC manually, so I page manually, so I can break all can save contents that I couldn't your invariants and output some add the honest way! garbage! 7 Comet Components How Many Zombies Can You Barbecue? Display the chat GUI in a part of the page of my choosing. Subtree of Dynamic Page Structure Chat Client Persistent Channel for Server Comm. Replace chat log with “BRAAAAAINS”!!! ? Main App Pretend to be the user and send a message to the channel in his name! Facebook 8 Back to Basics.... Subtree of Dynamic Page Structure Users Table Authentication Writable Area Server-Side RPC Handler Login Cookie How do I dispatch from URLs to all of my different components? Combined Application 9 Code Generation DB Schema Standard DB Admin Interface “Scaffolding” Output program code as strings? Gross! Use run-time reflection? Breaks all the abstractions we just saw.... What is this and how do I use it? The manual? Yeah, it's sometimes even accurate! The source code? :-O Examples? This is what happens today.... 10 My Solutions ● Strongly-encapsulated web components? – First-class language support for the key pieces of web applications – No loopholes! – Now use the standard abstractions of functional programming. ● Principled metaprogramming? – Statically-typed metaprograms, using language ideas from the world of dependent types. 11 Ur/Web Ur/Web, a special standard library and compiler Supporting modern web app development Web 1.0: Links, forms, etc. Web 2.0: AJAX and Comet SQL database access Ur, a new general purpose language Inspired by ML and Haskell, but with even richer type system features 12 Advantages Productivity Security Performance Important pieces of web applications are first-class. Any code to be interpreted is not “just a string.” New ways of structuring programs. Rules out: Optimizing compiler produces fast & memory-efficient native code. New approach to metaprogramming. Cross-site scripting Code injection Malicious file exec. Cross-site req. forgery ... No garbage collection! Domain-specific optimizations 13 Hello World! fun main () = return Hello world!

Hello world!

14 Hello ___! functor Hello(M : sig val text : string end) : sig val main : unit → page end = struct fun main () = return Hello {[M.text]}!

Hello {[M.text]}!

end 15 Two Hellos, Living in Harmony structure World = Hello(struct val text = “world” end) structure Boston = Hello(struct val text = “Boston” end) fun main () = return

Pick your poison:

  • World
  • Boston
  • 16 Encapsulation structure Auth : sig val loginForm : unit → xbody val whoami : unit → string end = struct table users : {Nam : string, Pw : string} cookie auth : {Nam : string, Pw : string} fun rightInfo r = oneRow (SELECT COUNT(*) FROM users WHERE Nam = {[r.Nam]} AND Pw = {[r.Pw]}) = 1 fun login r = if rightInfo r then setCookie auth r else error “Wrong info!” fun loginForm () = (* Form handled by 'login'... *) fun whoami () = let r = getCookie auth in if rightInfo r then r.Nam else error “Wrong info!” end 17 Some Client Code fun main () = return {Auth.loginForm ()}

    Welcome. You could go somewhere.

    and somewhere () = user ← Auth.whoami (); if user = “Fred Flintstone” then return Yabba dabba doo! else return Boring and evil () = oneRow (SELECT Pw FROM Auth.user WHERE Nam = 'Admin') 18 Functional-Reactive GUIs The Status Quo: A B The Reactive Way: Document Tree (DOM) Change the value of this data source. Script C Data Source Find the node named “B” and replace its contents. D .... Data Source Module Pure Function A B C Script D D 19 A Client-Side Counter structure Counter : sig type t val new : unit → t val increment : t → unit val render : t → xbody end = struct type t = source int fun new () = source 0 fun increment c = n ← get c; set c (n + 1) fun render c = {[n]}}/> end 20 Counter Client fun main () = c ← Counter.new (); return {Counter.render c}