[erlang-questions] Web server structure: Rack

Sean Cribbs <>
Sat Jan 9 19:23:34 CET 2010


Max,

Have you seen ewgi? It's similar to Rack and WSGI. 
http://code.google.com/p/ewgi/

Sean

On 1/9/10 12:50 PM, Max Lapshin wrote:
> Hi, I've promised to talk about better structure of web stack. I want
> to tell about Ruby on Rails experience.
> Basically Rails application is built according to MVC paradigm: Model,
> View, Controller. Perhaps everyone here have
> heard about it.
>
> Most interesting here will be speak about structure of View and
> Controller layers. Web application violates pure MVC structure,
> because in web application controller must present object of Model
> layer to template engine.
>
> So, after years of development, Rails came to the concept of Rack
> infrastructure.
>
> After parsing HTTP headers request is represented as hash table with
> http headers. Then this request is passed
> through configured chain of filters, that is ended with some handler.
>
> Let's look at an example config:
>
> use ActionController::Failsafe  # this is global exception handler,
> that captures all errors and show 500 in
> use ActionController::PageCache  # tries to find whole page cached
> map "/advert" do                     # enables mapping all requests to
> /advert to special handler.
>    run FastAdvertHandler
> end
>
> map "/" do                              # all other requests are
> moving to this section
>    use ActionController::Session::CookieStore, , {:secret=>"some_key",
> :session_key=>"_rails_session"}   # loads session from cookie
>    use ActionController::ParamsParser       # decode all params and
> parses query string
>    use Rack::Head                                    # discard body is HTTP HEAD
>    use Rails::Router                                  # checkout what
> controller and action will handle request
>    run Rails::Dispatcher
> end
>
>
> Each filter can store required information in mutable request, which
> is hash. Lets look at code of such filter:
>
>
> module Rack
>    module Session
>       class Cookie
>          def initialize(app, options = {})
>            @app = app
>            @key = options[:key] || "rack.session"   # Variables,
> starting from @ in ruby are just object instance variables
>            @secret = options[:secret]
>          end
>
>          def call(env)  # this method is by interface, requred method
> of each handler
>            load_session(env)      # this method take
>            status, headers, body = @app.call(env)        # this line is
> by interface required part of calling further request processing.
>            commit_session(env, status, headers, body)
>          end
>
>          def load_session(env)
>             env["rack.session"] = load_session_from_cookie(env[@key]) #
> here we take cookie, named the same as our key and decode it
>          end
>
>          def commit_session
>               ... # this method packs session to cookie back.
>          end
>       end
>    end
> end
>
>
> It is very important, that each filter can control, when to call
> subfilters up to last request handler.
> Second important thing, that there is defined convention, how to name
> request keys: env["rack.session"] is for session,
> env["request.error"] is for backtrace of request exceptions.
>
> Let's look, how would it be possible to repeat this structure in Erlang:
>
>
> -module(rack_server).
> -export([rack_config/0]).
>
> rack_config() ->
>    [
>      controller_failsafe,  % name of module
>      controller_cookiestore:new("secretstring", "_example_session"),
>      ...
>    ].
>
> Here is sketch:
> http://github.com/maxlapshin/erack/blob/master/src/example_server.erl
>
> so can look controller_failsafe module:
>
> -module(controller_failsafe).
>   -export([call/2]).
>   -behaviour(rack_handler).
>
> call(App, Request) ->
>    try App:call(Request) of
>      Reply ->  Reply
>    catch
>      error:notfound ->  [404, [{"Content-Type", "text/plain"}], "404 Not found"];
>      _:_ ->  [500, [{"Content-Type", "text/plain"}], "500 Server
> error"++lists:flatten(io_lib:format("~n~p~n",
> [erlang:get_stacktrace()]))]
>    end.
>
>
>
> Concept of Rack handlers became a glue idea for most ruby frameworks,
> making useless many of them, because they appeared to be just a one
> rack config with some set of handlers =)
>
> What do I want? To discuss this api and promote its implementation in
> erlang web servers. Also it would be great to extract implementation
> of the whole controller layer
> out of Zotonic CMS into reusable components. I'm willing to reuse its
> code in my applications, but it is impossible, because business logic
> and infrastructure logic are in one repository.
>
> ________________________________________________________________
> erlang-questions mailing list. See http://www.erlang.org/faq.html
> erlang-questions (at) erlang.org
>
>
>    



More information about the erlang-questions mailing list