Qu'est-ce que le middleware Rack dans Ruby? Je n'ai trouvé aucune bonne explication de ce qu'ils entendent par "middleware".
ruby-on-rails
ruby
http
web-applications
rack
chrisgoyal
la source
la source
Réponses:
Rack comme conception
L'intergiciel rack est plus qu'une "façon de filtrer une demande et une réponse" - c'est une implémentation du modèle de conception de pipeline pour les serveurs Web utilisant Rack .
Il sépare très clairement les différentes étapes du traitement d'une demande - la séparation des préoccupations est un objectif clé de tous les produits logiciels bien conçus.
Par exemple, avec Rack, je peux avoir des étapes distinctes du pipeline:
Authentification : lorsque la demande arrive, les informations de connexion des utilisateurs sont-elles correctes? Comment puis-je valider cet OAuth, authentification HTTP de base, nom / mot de passe?
Autorisation : "l'utilisateur est-il autorisé à effectuer cette tâche particulière?", C'est-à-dire la sécurité basée sur les rôles.
Mise en cache : ai-je déjà traité cette demande, puis-je retourner un résultat mis en cache?
Décoration : comment améliorer la demande pour améliorer le traitement en aval?
Surveillance des performances et de l'utilisation : quelles statistiques puis-je obtenir de la demande et de la réponse?
Exécution : gérer réellement la demande et fournir une réponse.
Être capable de séparer les différentes étapes (et éventuellement les inclure) est d'une grande aide pour développer des applications bien structurées.
Communauté
Il existe également un excellent écosystème autour du Rack Middleware - vous devriez pouvoir trouver des composants de rack prédéfinis pour effectuer toutes les étapes ci-dessus et plus encore. Voir le wiki Rack GitHub pour une liste de middleware .
Qu'est-ce que le middleware?
Le middleware est un terme épouvantable qui fait référence à tout composant logiciel / bibliothèque qui aide mais n'est pas directement impliqué dans l'exécution de certaines tâches. Des exemples très courants sont la journalisation, l'authentification et les autres composants de traitement horizontaux courants . Ce sont généralement les choses dont tout le monde a besoin dans plusieurs applications, mais pas trop de gens sont intéressés (ou devraient être) à se construire.
Plus d'information
Le commentaire selon lequel il s'agit d'un moyen de filtrer les demandes vient probablement de l' épisode 151 de RailsCast: Cast Screen Screen Middleware .
Le middleware de rack a évolué à partir de Rack et il y a une excellente introduction à Introduction au middleware de rack .
Il y a une introduction au middleware sur Wikipedia ici .
la source
Tout d'abord, Rack, c'est exactement deux choses:
Rack - L'interface du serveur Web
Les bases mêmes du rack sont une convention simple. Chaque serveur Web conforme au rack appellera toujours une méthode d'appel sur un objet que vous lui donnez et servira le résultat de cette méthode. Rack spécifie exactement à quoi doit ressembler cette méthode d'appel et ce qu'elle doit renvoyer. C'est du rack.
Essayons simplement. J'utiliserai WEBrick comme serveur Web compatible avec les racks, mais n'importe lequel d'entre eux fera l'affaire. Créons une application Web simple qui renvoie une chaîne JSON. Pour cela, nous allons créer un fichier appelé config.ru. Le config.ru sera automatiquement appelé par la commande rackup du rack gem qui exécutera simplement le contenu du config.ru dans un serveur Web compatible avec le rack. Ajoutons donc ce qui suit au fichier config.ru:
Comme la convention le précise, notre serveur a une méthode appelée call qui accepte un hachage d'environnement et retourne un tableau avec la forme [status, headers, body] pour le serveur web à servir. Essayons-le en appelant simplement rackup. Un serveur par défaut compatible rack, peut-être que WEBrick ou Mongrel démarrera et attendra immédiatement que les demandes soient traitées.
Testons notre nouveau serveur JSON en bouclant ou en visitant l'url
http://localhost:9292/hello.json
et le tour est joué:Ça marche. Génial! C'est la base de chaque framework web, que ce soit Rails ou Sinatra. À un moment donné, ils implémentent une méthode d'appel, parcourent tout le code du framework et retournent finalement une réponse sous la forme typique [état, en-têtes, corps].
Dans Ruby on Rails par exemple, les requêtes de rack atteignent la
ActionDispatch::Routing.Mapper
classe qui ressemble à ceci:Donc, fondamentalement, Rails vérifie, en fonction du hachage env si une route correspond. Si c'est le cas, il transmet le hachage env à l'application pour calculer la réponse, sinon il répond immédiatement avec un 404. Ainsi, tout serveur Web qui est conforme à la convention d'interface de rack est capable de servir une application Rails complètement soufflée.
Middleware
Rack prend également en charge la création de couches middleware. Ils interceptent essentiellement une demande, en font quelque chose et la transmettent. Ceci est très utile pour des tâches polyvalentes.
Supposons que nous souhaitons ajouter une journalisation à notre serveur JSON qui mesure également la durée d'une demande. Nous pouvons simplement créer un enregistreur de middleware qui fait exactement cela:
Lorsqu'il est créé, il enregistre lui-même une copie de l'application rack réelle. Dans notre cas, c'est une instance de notre JSONServer. Rack appelle automatiquement la méthode d'appel sur le middleware et attend un
[status, headers, body]
tableau, tout comme le retourne notre JSONServer.Ainsi, dans ce middleware, le point de départ est pris, puis l'appel réel au JSONServer est effectué avec
@app.call(env)
, puis l'enregistreur sort l'entrée de journalisation et renvoie finalement la réponse sous la forme[@status, @headers, @body]
.Pour que notre petit rackup.ru utilise ce middleware, ajoutez-lui un RackLogger comme ceci:
Redémarrez le serveur et le tour est joué, il génère un journal à chaque demande. Rack vous permet d'ajouter plusieurs middlewares qui sont appelés dans l'ordre où ils sont ajoutés. C'est juste un excellent moyen d'ajouter des fonctionnalités sans changer le cœur de l'application rack.
Rack - The Gem
Bien que le rack - tout d'abord - soit une convention, c'est aussi un joyau qui offre une grande fonctionnalité. Nous en avons déjà utilisé un pour notre serveur JSON, la commande rackup. Mais il y a plus! Le joyau du rack fournit de petites applications pour de nombreux cas d'utilisation, comme le service de fichiers statiques ou même des répertoires entiers. Voyons comment nous servons un fichier simple, par exemple un fichier HTML très basique situé à htmls / index.html:
Nous voulons peut-être servir ce fichier à partir de la racine du site Web, alors ajoutons ce qui suit à notre config.ru:
Si nous visitons,
http://localhost:9292
nous voyons notre fichier html parfaitement rendu. C'était facile, non?Ajoutons tout un répertoire de fichiers javascript en créant des fichiers javascript sous / javascripts et en ajoutant ce qui suit au config.ru:
Redémarrez le serveur et visitez
http://localhost:9292/javascript
et vous verrez une liste de tous les fichiers javascript que vous pouvez inclure maintenant directement de n'importe où.la source
J'ai eu du mal à comprendre Rack moi-même pendant un bon bout de temps. Je ne l'ai bien compris qu'après avoir travaillé moi-même à la création de ce serveur Web miniature Ruby . J'ai partagé mes connaissances sur Rack (sous la forme d'une histoire) ici sur mon blog: http://gauravchande.com/what-is-rack-in-ruby-rails
Les commentaires sont plus que bienvenus.
la source
config.ru
exemple exécutable minimalCourez
rackup
et visitezlocalhost:9292
. La sortie est:Il est donc clair que le
Middleware
wraps et appelle l'application principale. Par conséquent, il est capable de prétraiter la demande et de post-traiter la réponse de n'importe quelle manière.Comme expliqué sur: http://guides.rubyonrails.org/rails_on_rack.html#action-dispatcher-middleware-stack , Rails utilise les middlewares de Rack pour une grande partie de ses fonctionnalités, et vous pouvez aussi en ajouter vous-même avec
config.middleware.use
des méthodes familiales.L'avantage d'implémenter des fonctionnalités dans un middleware est que vous pouvez les réutiliser sur n'importe quel framework Rack, donc tous les Ruby majeurs, et pas seulement Rails.
la source
Le middleware de rack est un moyen de filtrer une demande et une réponse entrant dans votre application. Un composant middleware se situe entre le client et le serveur, traitant les demandes entrantes et les réponses sortantes, mais c'est plus qu'une interface qui peut être utilisée pour parler au serveur Web. Il est utilisé pour regrouper et ordonner les modules, qui sont généralement des classes Ruby, et spécifier la dépendance entre eux. Le module middleware de rack doit uniquement: - avoir un constructeur qui prend la prochaine application dans la pile comme paramètre - répondre à la méthode «call», qui prend le hachage de l'environnement comme paramètre. La valeur de retour de cet appel est un tableau de: code d'état, hachage d'environnement et corps de réponse.
la source
J'ai utilisé le middleware Rack pour résoudre quelques problèmes:
Il offrait des correctifs assez élégants dans les deux cas.
la source
Qu'est-ce que Rack?
Rack fournit une interface minimale entre les serveurs Web prenant en charge les frameworks Ruby et Ruby.
En utilisant Rack, vous pouvez écrire une application Rack.
Rack transmettra le hachage d'environnement (un hachage, contenu dans une demande HTTP d'un client, composé d'en-têtes de type CGI) à votre application de rack qui peut utiliser les éléments contenus dans ce hachage pour faire ce qu'il veut.
Qu'est-ce qu'une application en rack?
Pour utiliser Rack, vous devez fournir une «application» - un objet qui répond à la
#call
méthode avec le hachage d'environnement comme paramètre (généralement défini commeenv
).#call
doit renvoyer un tableau d'exactement trois valeurs:each
).Vous pouvez écrire une application Rack qui retourne un tel tableau - cela sera renvoyé à votre client, par Rack, dans une réponse (ce sera en fait une instance de la classe
Rack::Response
[cliquez pour accéder aux documents]).Une application en rack très simple:
gem install rack
config.ru
fichier - Rack sait le chercher.Nous allons créer une petite application en rack qui renvoie une réponse (une instance de
Rack::Response
) qui est le corps de réponse est un tableau qui contient une chaîne:"Hello, World!"
.Nous allons lancer un serveur local en utilisant la commande
rackup
.Lorsque vous visitez le port concerné dans notre navigateur, nous verrons "Bonjour, monde!" rendu dans la fenêtre.
Démarrez un serveur local avec
rackup
et visitez localhost: 9292 et vous devriez voir «Bonjour, World! rendu.Ce n'est pas une explication complète, mais essentiellement ce qui se passe ici est que le client (le navigateur) envoie une demande HTTP à Rack, via votre serveur local, et Rack instancie
MessageApp
et s'exécutecall
, en passant le hachage d'environnement en tant que paramètre dans la méthode ( lesenv
argument).Rack prend la valeur de retour (le tableau) et l'utilise pour créer une instance de
Rack::Response
et la renvoie au client. Le navigateur utilise la magie pour imprimer «Bonjour tout le monde! à l'écran.Soit dit en passant, si vous voulez voir à quoi ressemble le hachage de l'environnement, placez-le juste en
puts env
dessousdef call(env)
.Aussi minime soit-elle, ce que vous avez écrit ici est une application Rack!
Faire interagir une application en rack avec le hachage de l'environnement entrant
Dans notre petite application Rack, nous pouvons interagir avec le
env
hachage (voir ici pour en savoir plus sur le hachage Environnement).Nous mettrons en œuvre la possibilité pour l'utilisateur d'entrer sa propre chaîne de requête dans l'URL, par conséquent, cette chaîne sera présente dans la demande HTTP, encapsulée en tant que valeur dans l'une des paires clé / valeur du hachage d'environnement.
Notre application Rack accédera à cette chaîne de requête à partir du hachage d'environnement et la renverra au client (notre navigateur, dans ce cas) via le corps de la réponse.
À partir des documents Rack sur le hachage d'environnement: "QUERY_STRING: la partie de l'URL de demande qui suit le?, Le cas échéant. Peut être vide, mais est toujours obligatoire!"
Maintenant,
rackup
et visitezlocalhost:9292?hello
(?hello
étant la chaîne de requête) et vous devriez voir «bonjour» rendu dans la fenêtre.Middleware de rack
Nous allons:
MessageSetter
,env
,MessageSetter
insérera une'MESSAGE'
clé dans le hachage env, sa valeur étant'Hello, World!'
sienv['QUERY_STRING']
est vide;env['QUERY_STRING']
si non,@app.call(env)
-@app
être la prochaine application de la « pile »:MessageApp
.Tout d'abord, la version «longue»:
À partir des documents Rack :: Builder, nous voyons que
Rack::Builder
implémente un petit DSL pour construire de manière itérative des applications Rack. Cela signifie essentiellement que vous pouvez créer une «pile» composée d'un ou plusieurs middlewares et d'une application de «bas niveau» vers laquelle envoyer. Toutes les demandes transmises à votre application de niveau inférieur seront d'abord traitées par votre ou vos middleware.#use
spécifie le middleware à utiliser dans une pile. Il prend le middleware comme argument.Le middleware de rack doit:
call
méthode qui prend le hachage d'environnement comme paramètre.Dans notre cas, le «middleware» est
MessageSetter
, le «constructeur» est lainitialize
méthode de MessageSetter , la «prochaine application» dans la pile estMessageApp
.Donc ici, à cause de ce qui se
Rack::Builder
passe sous le capot, l'app
argument deMessageSetter
lainitialize
méthode estMessageApp
.(faites le tour de la tête avant de continuer)
Par conséquent, chaque élément du middleware `` transmet '' essentiellement le hachage d'environnement existant à l'application suivante de la chaîne - vous avez donc la possibilité de muter ce hachage d'environnement au sein du middleware avant de le transmettre à l'application suivante de la pile.
#run
prend un argument qui est un objet qui répond#call
et renvoie une réponse de rack (une instance deRack::Response
).Conclusions
En utilisant
Rack::Builder
vous pouvez construire des chaînes de middlewares et toute demande à votre application sera traitée à tour de rôle par chaque middleware avant d'être finalement traitée par la dernière pièce de la pile (dans notre cas,MessageApp
). Ceci est extrêmement utile car il sépare les différentes étapes du traitement des demandes. En termes de «séparation des préoccupations», cela ne pourrait pas être beaucoup plus propre!Vous pouvez construire un «pipeline de demandes» composé de plusieurs middlewares qui traitent de choses telles que:
(au-dessus des puces d'une autre réponse sur ce fil)
Vous le verrez souvent dans les applications professionnelles Sinatra. Sinatra utilise Rack! Voir ici pour la définition de ce que Sinatra EST !
En guise de note finale, notre
config.ru
peut être écrit dans un style abrégé, produisant exactement la même fonctionnalité (et c'est ce que vous verrez généralement):Et pour montrer plus explicitement ce qui
MessageApp
se passe, voici sa version «longue» qui montre explicitement que#call
crée une nouvelle instance deRack::Response
, avec les trois arguments requis.Liens utiles
la source
Rack - L'interface b / w Web & App Server
Rack est un package Ruby qui fournit une interface permettant à un serveur Web de communiquer avec l'application. Il est facile d'ajouter des composants middleware entre le serveur Web et l'application pour modifier le comportement de votre demande / réponse. Le composant middleware se situe entre le client et le serveur, traitant les demandes entrantes et les réponses sortantes.
En termes simples, il s'agit essentiellement d'un ensemble de directives sur la façon dont un serveur et une application Rails (ou toute autre application Web Ruby) doivent se parler .
Pour utiliser Rack, fournissez une "application": un objet qui répond à la méthode d'appel, en prenant le hachage de l'environnement comme paramètre et en renvoyant un tableau avec trois éléments:
Pour plus d'explications, vous pouvez suivre les liens ci-dessous.
Dans les rails, nous avons config.ru comme fichier rack, vous pouvez exécuter n'importe quel fichier rack avec la
rackup
commande. Et le port par défaut pour cela est9292
. Pour tester cela, vous pouvez simplement exécuterrackup
dans votre répertoire rails et voir le résultat. Vous pouvez également attribuer le port sur lequel vous souhaitez l'exécuter. La commande pour exécuter le fichier rack sur n'importe quel port spécifique estla source
Le rack est un joyau qui fournit une interface simple pour abstraire les requêtes / réponses HTTP. Le rack se situe entre les cadres Web (Rails, Sinatra, etc.) et les serveurs Web (licorne, puma) en tant qu'adaptateur. De l'image ci-dessus, cela permet au serveur de licorne d'être complètement indépendant de connaître les rails et les rails ne connaissent pas la licorne. Ceci est un bon exemple de couplage lâche , de séparation des préoccupations .
L'image ci-dessus provient de cette conférence sur les rails sur le rack https://youtu.be/3PnUV9QzB0g Je recommande de le regarder pour une compréhension plus approfondie.
la source