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.

Laisser une réponse

 
Fork me on GitHub