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"=>#, "rack.version"=>[1, 0], "rack.errors"=>#>, "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"=>#, "async.close"=>#} === Metoda call === Metoda ''call'' ma zwracać tablicę z trzema elementami: * kod odpowiedzi HTTP, np. 200, * ''hash'' lub 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ę ''each'' i wywołać podany blok ''string''ami. === config.ru === Najczęściej uruchamia się ''Rack''a 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. FIXME 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''.