Skip to content

Elixir wrapper around erlang Basho Webmachine

License

Notifications You must be signed in to change notification settings

xirdev/ewebmachine

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

30 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Ewebmachine

Ewebmachine is a very simple Elixir DSL around Webmachine from basho : https://github.com/basho/webmachine

Ewebmachine modules

Resources module are grouped into a module which has to use Ewebmachine.

defmodule MyApp1 do
  use Ewebmachine

  resource ['hello',:name] do
    to_html do:
      """
      <html>
        <body>
          <h1> Hello #{:wrq.path_info(:name,_req)} </h1>
        </body>
      </html>
      """
  end

Each "resource" declares a webmachine resource module. The resource takes the route as a parameter, so that MyApp1.routes returns the list of webmachine dispatch rules corresponding to the resources declared in MyApp1.

Default Supervisor

Ewebmachine.Sup is a default supervisor for web application, it launches mochiweb configured to use webmachine with the following configuration options (start_link dictlist parameter):

  • listen ip : default to "0.0.0.0"
  • listen port : default to 7272
  • log_dir : default to "priv/log"
  • modules : lists the ewebmachine module routes to be include, mandatory

Initial State

An initial state (which is used in webmachine "init" function) can be declared with ini, the default one is a list (because of the resource function response shortut described below)

resource [] do
  ini [:init]
end

Webmachine debug mode

The trace mode is activated for every resources when executed in Mix dev environment. Traces are stored in directory defined by {:webmachine,:trace_dir} if defined, else in /tmp.

Default Supervisor add the /debug route to access the webmachine traces in dev environment.

Resource Functions

Resource functions can be declared directly by name, body-producing function must start with to_* or from_*. Every resource functions are declared without ReqData and Context parameters declaration, which are implicitly declared as variable \_req and _ctx.

Resource functions response shortcuts

The resource functions response is wrap so that you replace the standard {res,req,ctx} webmachine response by :

  • res is a shortcut to {res,_req,_ctx}
  • pass(res, opt1: value1, opt2: value2) is a shortcut to {res,_req,updated_ctx} where updated_ctx is the listdict merge between old listdict state and keywords arguments (opt1,opt2 here), works only if _ctx is a dictlist

So for instance, the following resource functions are equivalent :

resource_exists do: true
resource_exists do: {true,_req,_ctx}

And you can transmit some variable in the context like this :

resource ['user',:name] do
  resource_exists do
     user = User.get(:wrq.path_info(:name,_req))
     pass user != nil, user: user
  end
  to_html do: (_ctx[:user] |> template("user_template"))
end

Example usage

Declare two ewebmachine module :

defmodule WebMain do
  use Ewebmachine

  resource [] do
    to_html do: "<html><body>Hello world</body>"
  end

  resource['sitemap'] do
    content_types_provided do: [{'application/xml',:to_xml}]
    to_xml do
      """
      <?xml version="1.0" encoding="UTF-8"?>
      <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
      <url>
          <loc>http://mon-domaine.fr/</loc>
          <lastmod>2012-12-15</lastmod>
          <changefreq>daily</changefreq>
          <priority>1</priority>
      </url>
      </urlset>
      """
    end
  end
end

defmodule WebContact do
  use Ewebmachine

  resource ['contact'] do
    to_html do: "<html><body>contact page</body>"
  end
end

Then to launch the webserver, add the supervisor in your App tree with the Ewebmachine.Sup.start_link functions. You can configure here the port/ip and the ewebmachine modules to be included.

defmodule MySup do
  use Supervisor.Behaviour
  def start_link, do: :supervisor.start_link({:local,__MODULE__},__MODULE__,[])
  def init([]) do
    supervise([
      supervisor(Ewebmachine.Sup,[[modules: [WebMain,WebContact],port: 8080]]),
      supervisor(MyOtherSup,[])
    ], strategy: :one_for_one)
  end
end

Example Configuration

As configuration of Ewebmachine.Sup is passed "as is" to webmachine_mochiweb then to mochiweb_socket, you can configure your entire configuration as you wish when launching the supervisors.

Below an example configuration : listen HTTP on 0.0.0.0:80 and ::80 with a redirect handler => https://samehost/samepath then listen HTTPS on 0.0.0.0:443 and ::443 with applications handlers.

defmodule SSLRedirect do
  use Ewebmachine
  resource [:*] do
    resource_exists do: false
    previously_existed do: true
    moved_permanently do:
      {true,'https://#{hostname(_req)}#{:wrq.raw_path(_req)}'}
    defp hostname(req), do:
      "#{:wrq.get_req_header('host',req)}"|>String.split(":")|>Enum.at(0)
  end
end
defmodule MySup do
  use Supervisor.Behaviour
  def start_link, do: :supervisor.start_link({:local,__MODULE__},__MODULE__,[])
  def init([]) do
    http = [{"0.0.0.0",80},{"::",80}]
    https = [{"0.0.0.0","/etc/certs/my.crt","/etc/certs/my.pem"},{"::","/etc/certs/my.crt","/etc/certs/my.pem"}]
    supervise(
        (http|>Enum.map(fn {ip,port}-> 
          supervisor(Ewebmachine.Sup,[[modules: [SSLRedirect],ip: '#{ip}', port: port ]],id: :"web#{inspect ip}#{port}")
        end))++
        (https|>Enum.map(fn {ip,cert,key}-> 
          supervisor(Ewebmachine.Sup,[[modules: [WebMain,WebContact],ip: '#{ip}', port: 443, ssl: true, ssl_opts: [certfile: '#{cert}', keyfile: '#{key}']]],id: :"web#{inspect ip}443")
        end))
      ], strategy: :one_for_all)
  end
end

About

Elixir wrapper around erlang Basho Webmachine

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Elixir 100.0%