class: middle # Raxx ## An Elixir webserver interface ??? I want to talk about a library I have been developing over the past few months. --- class: middle # Based on Rack Rack is a Ruby web server interface. ??? Sorry if from other languages but its my background. --- class: middle # But with two X's I really like elixir. ??? Let's get started. --- class: middle # Plug ??? But there is an elephant in the room. --- class: middle ## Ermmmm? ??? Plug is a nice library. But reading through the source I found one problem. --- class: middle # Motivation ```elixir %Plug.Conn{owner: pid} = conn ``` ??? Eliminate impurity - read haskell write elixir to purge the OO ALSO More than one implementation is healthy --- class: middle # Principle > The stateless HTTP request response model fulfills a valuable role in modern applications. > It will continue to do so, this simple usecase should not be compicated by catering to more advanced communication patterns. --- class: middle # Simple HTTP request -> application -> response --- class: middle # Simple Raxx ```elixir defmodule MySimpleApp do def handle_request(_request, _env), do: Raxx.Response.ok() end ``` ??? Now this looks similar to a plug handler and it is. But with the pesky owner pid gone we don't have to keep passing around the modified conn. --- class: middle # Request ```elixir %Raxx.Request{ host: "www.example.com", method: "GET", path: ["some", "path"], ... } ``` ??? Just a translation of the HTTP request. A Request object has a 1 - 1 mapping with a HTTP request. --- class: middle ```elixir defmodule Router do import Raxx.Request def handle_request(%{path: ["users"], method: method}, _) do case method do "GET" -> # Get all the users... "POST" -> # Create a user... end end def handle_request(request = %{path: ["api" | rest]}, env) do ApiRouter.handle_request(%{request | path: rest}, env) end end ``` ??? This is my favourite part. it shows off the power of the built in tools that come with elixir. It is my opinion that this power is why elixir can progress so fast even with a smaller ecosystem of packages No routing DSL needed. Only concession is to split the path. Make the struct part of the API. --- class: middle # Response ```elixir %Raxx.Response{ status: 200, headers: %{}, body: "hello" } ``` ??? Plus one cheeky error field that is used if you are controlling applications with trys or catches. --- class: middle ```elixir defmodule FooRouter do alias Raxx.Response def handle_request(%{path: ["users"], method: "GET"}, _) do %{status: 200, body: "All users: Andy, Bethany, Clive"} end def handle_request(%{path: ["users"], method: "POST", body: data}, _) do case MyApp.create_user(data) do {:ok, user} -> Response.created("New user #{user}") {:error, :already_exists} -> Response.conflict("sorry") {:error, :bad_params} -> Response.bad_request("sorry") {:error, _unknown} -> Response.internal_server_error("Well that's weird") end end def handle_request(%{path: ["users"], method: _}, _) do Response.method_not_allowed("Don't do that") end end ``` ??? Helpers just for the purpose of generating responses. Talk about umbrella apps. Talk about debugger page and the fact that if the error is within the application write a new test which ignores the webstack. --- class: middle # But ... --- class: middle # Streaming ??? The future of the web is real and streaming is here. It would be nice to have --- class: middle ```elixir defmodule StreamingApp do alias Raxx.Response alias Raxx.ServerSentEvents, as: SSE def handle_request(%{path: ["events"]}, %{channel: channel}) do :ok = MyApp.subscribe(channel, self()) SSE.upgrade(__MODULE__, :no_state) end def handle_info({:update, message}, _) do {:send, message} end def handle_info(_, _) do :nosend end end ``` ??? Expand the communication protocol without impacting on the simplicity of response only. TODO Streaming in, and websockets. Integrations. Elli, Cowboy, mochiweb and Ace. --- class: middle # Me -> @CrowdHailer [https://github.com/crowdhailer/raxx](https://github.com/crowdhailer/raxx) ??? All comments well recieved. As an experiment I am trying to develop this as a learning process rather than a thing which has to be highly effecient. I am also build a web server in the same educational vein. So please get in touch. I would love some well mannered arguments on the topic. Thank you very much.