Parlons un peu de rack
Utilisé par rails et de nombreuses autres applications ruby afin de pouvoir être lancées par une large majorité de serveurs web (mongrel, unicorn, …) rack est particulièrement puissant.
La création d’une première application est on ne peut plus simple.
Dans un fichier test.rb :
class Test
def call(env)
[200, {"Content-Type" => "text/html"}, ["<html><head></head><body>Hello world!</body></html>"]]
end
end
Exécutez votre application avec la ligne de commande suivante :
rackup test.rb
Simple mais efficace
Bien évidemment il faut ajouter des librairies à cela afin d’avoir quelque chose de plus puissant.
Maintenant découvronr autre chose : les middlewares.
En effet rack peut embriquer les méthodes call et ainsi vous permettre d’exécuter du code juste après l’initialisation de rack. Ou bien juste avant l’exécution du code de votre page.
Le développement d’un rack ressemble fortement à celui d’une tâche rack « normale ».
Voici un exemple de middleware vous permettant d’ajouter, juste avant la balise
, le temps d’exécution de la page.
Dans un fichier response_timer.rb
class ResponseTimer
attr_reader :message, :app
def initialize(app, message = "Response Time")
@message = message
@app = app
end
def call(env)
start = Time.now
status, headers, response = app.call(env)
stop = Time.now
body = ''
response.each { |part| body << part }
index = body.rindex('</body>')
if index
body.insert(index, "<!-- #{message}: #{stop - start} -->\n")
headers["Content-Length"] = body.length.to_s
response = [body]
end
[status, headers, response]
end
end
En revanche, nous allons maintenant avoir besoin d’un fichier de configuration pour rack, afin de pouvoir définir quel middleware nous incluons.
Nous devons pour cela créer un fichier nommé config.ru
require 'test'
require 'response_timer'
use ResponseTimer
run Test.new
Et nous n’avons plus qu’à exécuter le serveur
rackup
Vous noterez trois choses :
Nous incluons les deux librairies que nous venons de créer. Notre application et le middleware
Avec la méthode « use », nous ajoutons le middle à ceux natif à rack
Nous exécutons notre application
Comment ce middleware fonctionne-t-il ?
Comme votre application !
Vous constaterez que les deux ont une méthode call. Et que les deux retournent un tableau contenant status, headers et réponse.
La seule différence entre les deux étant cette ligne :
status, headers, response = app.call(env)
Dans le middleware :
Grace au app.call, nous appellons le middleware suivant. Et ce, jusqu’à ce que nous arrivions au bout de la chaine : notre classe « test ».
Nous calculons donc assez aisément le temps d’exécution de notre application. Il nous suffit de faire la différence entre le timestamp avant l’exécution de cette méthode et après.
Et comme nous avons accès au contenu de la page retournée même après l’exécution de la méthode, nous pouvons y ajouter un commentaire juste avant la balise (si elle existe) contenant le temps d’exécution de la page.
Et dans rails ?
Comme dit plus haut, toute application rails tourne avec rack. Il est donc tout à fait possible d’ajouter notre middleware dans votre application.
Dans rails, les middlewares sont à ajouter dans le fichier config/environment.rb.
Voici comment j’ai inclu le rack ResponseTimer :
Rails::Initializer.run do |config|
config.middleware.insert_before Rack::Lock, "ResponseTimer", "Load Time"
end
Le middleware Rack::Lock est le tout premier à être exécuté (vous pouvez avoir la liste de tous vos middlewares avec rake middleware).
Nous exécutons donc, juste avant celui-ci, le calcul du temps d’exécution de notre page
Trois méthodes vous permettent d’ajouter de nouveaux middlewares :
config.middleware.use – Le middleware sera ajouté à la fin de la pile
config.middleware.insert_before – Le middleware sera ajouté avant celui passé en premier paramètre
config.middleware.insert_after – Le middleware sera ajouté après celui passé en premier paramètre
Vous pouvez également supprimer un middleware précédemment ajouté : config.middleware.delete
Et remplacer un middleware par un autre : config.middleware.swap
Par ailleurs de nombreux middlewares sont disponibles en Open Source. Vous en trouverez une liste sur le wiki de rack.
Ainsi que dans le projet rack-contrib.