Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

2015-10-07 PPDC HTTP Adapters

210 views

Published on

Survey of HTTP adapter technologies sharing the middleware concept.

Examples: Ring, WSGI, Rack

Published in: Technology
  • Be the first to like this

2015-10-07 PPDC HTTP Adapters

  1. 1. HTTP Adapers Polyglot Programming DC 2015 Brock Wilcox awwaiid@thelackthereof.org
  2. 2. Web Applications
  3. 3. Request → Response
  4. 4. Let's go BACK....
  5. 5. to 1993
  6. 6. CGI Common Gateway Interface
  7. 7. Request → Response
  8. 8. ... Unix!
  9. 9. Request → Response ENV + STDIN → STDOUT ENV == Headers (params) STDIN == POST STDOUT == Headers + Body
  10. 10. #!/bin/sh # A lovely cgi application echo "Content-type: text/html" echo echo "Hello, world! Query:" echo $QUERY_STRING
  11. 11. Parse the query string if you want
  12. 12. cgi programs rise from ash then burn again upon each request
  13. 13. Long running applications
  14. 14. Kinda long-running mod_perl mod_php mod_python ...
  15. 15. Kinda long-running FastCGI
  16. 16. Just run your own HTTPD
  17. 17. Also annoying
  18. 18. Same webserver language, but unlink from webserver.
  19. 19. Web App Frameworks
  20. 20. func app(request) → response response = [ status, headers, body ]
  21. 21. Common Lisp - Clack Clojure - Ring Elixir - Plug Haskell - Hack2 Java - Servlets? Javascript - JSGI Lua - WSAPI Perl - PSGI Perl6 - P6SGI Python - WSGI Ruby - Rack Scala - SSGI * - uWSGI
  22. 22. # Python WSGI def application(environ, start_response): start_response('200 OK', [('Content-Type', 'text/plain')]) yield 'Hello, world!'
  23. 23. # Ruby Rack app = lambda do |env| [200, {"Content-Type" => "text/plain"}, ["Hello, world!"]] end
  24. 24. # Perl PSGI my $app = sub { my ($env) = @_; return [200, ['Content-Type' => 'text/plain'], ["Hello, world!"]]; }
  25. 25. // Javascript JSGI require("jsgi-node").start(function(request){ return { status:200, headers:{}, body:["Hello, world!"] }; });
  26. 26. # Elixir Plug defmodule MyPlug do import Plug.Conn def init(options) do # initialize options options end def call(conn, _opts) do conn |> put_resp_content_type("text/plain") |> send_resp(200, "Hello, world!") end end
  27. 27. ; Clojure Ring (ns hello-world.core) (defn handler [request] {:status 200 :headers {"Content-Type" "text/html"} :body "Hello World"})
  28. 28. # Perl6 P6SGI sub app(%env) { start { 200, [ Content-Type => 'text/plain' ], [ 'Hello World!' ] } }
  29. 29. // Scala SSGI package org.scalatra.ssgi package examples.servlet import scala.xml.NodeSeq class HelloWorldApp extends Application { def apply(v1: Request) = Response(body = <h1>Hello, world!</h1>) }
  30. 30. Lua WSAPI function hello(wsapi_env) local headers = { ["Content-type"] = "text/html" } local function hello_text() coroutine.yield("Hello, world!") end return 200, headers, coroutine.wrap(hello_text) end
  31. 31. // Java Servlet // Import required java libraries import java.io.*; import javax.servlet.*; import javax.servlet.http.*; // Extend HttpServlet class public class HelloWorld extends HttpServlet { private String message; public void init() throws ServletException { // Do required initialization message = "Hello, world!"; } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // Set response content type response.setContentType("text/html"); // Actual logic goes here. PrintWriter out = response.getWriter(); out.println("<h1>" + message + "</h1>"); } public void destroy() { // do nothing. } }
  32. 32. {-# Haskell #-} {-# LANGUAGE OverloadedStrings #-} import Hack2 import Hack2.Contrib.Response (set_body_bytestring) import Hack2.Handler.SnapServer app :: Application app = env -> return $ Response 200 [ ("Content-Type", "text/plain") ] "Hello, world!" main = run app
  33. 33. Streaming response = [status, headers, callback] Keep invoking callback until done
  34. 34. Streaming response = [status, headers, promise] Wait for promise results, maybe chained
  35. 35. Streaming / Websockets ... not unified
  36. 36. Middleware
  37. 37. app: request → response middleware: app → (request → response)
  38. 38. def middlin(app) lambda do |request| # ... mess with request app_response = app(request) # ... mess with app_response app_response end end
  39. 39. def log_middleware(app) lambda do |request| File.open("middleware.log", "w+") do |f| f.puts request end app_response = app(request) app_response end end app = lambda do |env| [200, {"Content-Type" => "text/plain"}, ["Hello, world!"]] end new_app = log_middleware(app)
  40. 40. Middleware Examples Logging Authenticating Proxy Multi-app routing Session tracking Debugging Content filtering Content translation** Content injection Static serving
  41. 41. THE END

×