Rack to bardzo prosty protokół, który specyfikuje sposób komunikacji serwera HTTP z obiektem aplikacji. Protokół ten mówi, że obiekt aplikacji musi odpowiadać na metodę call. Serwer wywoła tą metodę z jednym parametrem, w którym zawarte będą wszystkie niezbędne informacje o żądaniu (jest to Hash zawierający takie informacje jak ścieżka żądania, słowo HTTP, nagłówki, etc.).
Uruchamianie
Najprostszy przykład ilustrujący Racka mieści się w kilku ledwie linijkach:
require 'rack' require 'pp' class Racking def call(env) pp env return [200, {}, [""]] end end Rack::Handler::Thin.run(Racking.new, Port: 9000)
Po wizycie na localhost:9000 na wyjściu programu pojawi się wspomniany wcześniej Hash z informacjami o żądaniu:
{"SERVER_SOFTWARE"=>"thin 1.5.0 codename Knife", "SERVER_NAME"=>"localhost", "rack.input"=>#<StringIO:0x007ff6c4b0c968>, "rack.version"=>[1, 0], "rack.errors"=>#<IO:<STDERR>>, "rack.multithread"=>false, "rack.multiprocess"=>false, "rack.run_once"=>false, "REQUEST_METHOD"=>"GET", "REQUEST_PATH"=>"/", "PATH_INFO"=>"/", "REQUEST_URI"=>"/", "HTTP_VERSION"=>"HTTP/1.1", "HTTP_HOST"=>"localhost:9000", "HTTP_CONNECTION"=>"keep-alive", "HTTP_USER_AGENT"=> "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.101 Safari/537.11", "HTTP_ACCEPT"=> "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "HTTP_ACCEPT_ENCODING"=>"gzip,deflate,sdch", "HTTP_ACCEPT_LANGUAGE"=>"en-US,en;q=0.8", "HTTP_ACCEPT_CHARSET"=>"ISO-8859-1,utf-8;q=0.7,*;q=0.3", "GATEWAY_INTERFACE"=>"CGI/1.2", "SERVER_PORT"=>"9000", "QUERY_STRING"=>"", "SERVER_PROTOCOL"=>"HTTP/1.1", "rack.url_scheme"=>"http", "SCRIPT_NAME"=>"", "REMOTE_ADDR"=>"127.0.0.1", "async.callback"=>#<Method: Thin::Connection#post_process>, "async.close"=>#<EventMachine::DefaultDeferrable:0x007ff6c4b32ac8>}
Metoda call
Metoda call ma zwracać tablicę z trzema elementami:
- kod odpowiedzi HTTP, np. 200,
hashlub podobny hashowi obiekt, zawierający nagłówki odpowiedzi (rozmiar odpowiedzi, czy cache'ować, etc.),- treść odpowiedzi, która ma się zachowywać jak tablica łańcuchów znaków, tj. odpowiadać na metodę
eachi wywołać podany blokstringami.
config.ru
Najczęściej uruchamia się Racka za pomocą komendy rackup, która korzysta z pliku konfiguracyjnego config.ru. Przykładowy plik mógłby wyglądać następująco:
Middleware
Specyfikacja przewiduje również możliwość tworzenia łańcuchów filtrów i routerów przed aplikacją. Te są ogólnie nazywane jako middleware. One również odpowiadają na metodę call i zwracają omówioną wcześniej tablicę. Taki filter może zmodyfikować żądanie, przekazać je lub zatrzymać.
Tworzenie
middleware jest tworzony poprzez obiekt factory. Taki obiekt musi odpowiadać na metodę new, przymującą conajmniej jeden parametr - aplikację (może nią być kolejny middleware), do której ma przekazać zmodyfikowany hash z żądaniem.
Utworzyć własny
class MyMiddleware def initialize(app) @app = app end def call(env) if env['PATH_INFO'] == '/' @app.call(env) else [404, {'Content-Type' => 'text/plain'}, ['not ok']] end end end
Na żądania poza ścieżkę główną, wysłana zostanie odpowiedź 404, not ok.
