Was ist Rack-Middleware?


265

Was ist Rack-Middleware in Ruby? Ich konnte keine gute Erklärung dafür finden, was sie unter "Middleware" verstehen.


4
Es gibt auch eine Anleitung auf RailsGuide, die Rack jetzt umfassend behandelt, einschließlich Middleware : guides.rubyonrails.org/rails_on_rack.html
xji

Vielen Dank an das PhusionPassenger-Team, das einen gut erklärten Artikel in seinem Blog hat. rubyraptor.org/...
Lamian

Rack und Rack-Middleware werden in DIESEM Artikel erläutert . Außerdem wird das Erstellen einer Rack-basierten Anwendung erläutert.
Shashwat Srivastava

Antworten:


352

Rack als Design

Rack-Middleware ist mehr als "eine Möglichkeit, eine Anfrage und Antwort zu filtern" - es ist eine Implementierung des Pipeline-Entwurfsmusters für Webserver, die Rack verwenden .

Die verschiedenen Phasen der Bearbeitung einer Anfrage werden sehr sauber voneinander getrennt. Die Trennung von Bedenken ist ein zentrales Ziel aller gut gestalteten Softwareprodukte.

Zum Beispiel kann ich mit Rack separate Phasen der Pipeline ausführen:

  • Authentifizierung : Sind die Anmeldedaten des Benutzers korrekt, wenn die Anforderung eingeht? Wie überprüfe ich diese OAuth, HTTP Basic Authentication, Name / Passwort?

  • Autorisierung : " Ist der Benutzer berechtigt, diese bestimmte Aufgabe auszuführen?", Dh rollenbasierte Sicherheit.

  • Caching : Habe ich diese Anfrage bereits bearbeitet? Kann ich ein zwischengespeichertes Ergebnis zurückgeben?

  • Dekoration : Wie kann ich die Anfrage verbessern, um die Weiterverarbeitung zu verbessern?

  • Leistungs- und Nutzungsüberwachung : Welche Statistiken kann ich aus der Anfrage und Antwort erhalten?

  • Ausführung : Behandeln Sie die Anforderung tatsächlich und geben Sie eine Antwort.

Die Möglichkeit, die verschiedenen Phasen zu trennen (und optional einzuschließen), ist eine große Hilfe bei der Entwicklung gut strukturierter Anwendungen.

Gemeinschaft

Es gibt auch ein großartiges Ökosystem, das sich um Rack Middleware entwickelt - Sie sollten in der Lage sein, vorgefertigte Rack-Komponenten zu finden, um alle oben genannten Schritte und mehr auszuführen. Eine Liste der Middleware finden Sie im Rack GitHub-Wiki .

Was ist Middleware?

Middleware ist ein schrecklicher Begriff, der sich auf jede Softwarekomponente / Bibliothek bezieht, die bei der Ausführung einer Aufgabe hilft, aber nicht direkt daran beteiligt ist. Sehr häufige Beispiele sind Protokollierung, Authentifizierung und die anderen gängigen horizontalen Verarbeitungskomponenten . Dies sind in der Regel die Dinge, die jeder für mehrere Anwendungen benötigt, aber nicht zu viele Menschen sind daran interessiert (oder sollten es sein), sich selbst aufzubauen.

Mehr Informationen


Eines ist mir unklar: Teilen alle Middleware dieselben Daten? Ist es möglich, sie aus Sicherheitsgründen zu trennen (z. B. Sandbox 1)?
Brian Armstrong

2
Das Rack ist Teil Ihrer Anwendung, sodass alle Middleware-Komponenten dieselbe Kopie der Anforderung haben und diese nach Belieben ändern können. AFAIK, es gibt keine Möglichkeit, sie auf dieselbe Weise zu sandboxen, wie es nicht möglich ist, ein Objekt innerhalb desselben Prozesses von einem anderen zu sandboxen (ungeachtet der Versuche, Ruby-Sandboxing durchzuführen).
Chris McCauley

1
und Verstehe, dass Rack anders ist als Rake.
Manish Shrivastava

1
Ich stelle mir Middleware gerne als alles vor, was sich in der Mitte meiner App zwischen dem, was ich codiert habe, und dem, was zu und von meinem Server geht, befindet. Dieser wird auf dem Rackspace gehostet. Der Grund, warum der Begriff "Rack-Middleware", wie wir alle wissen, verwirrend ist, liegt darin, dass Konfuzius vor mehr als 2000 Jahren die gesamte ursprüngliche Rack-Middleware geschrieben hat. In Frankreich.
LpLrich

74

Zunächst einmal ist Rack genau zwei Dinge:

  • Eine Webserver-Schnittstellenkonvention
  • Ein Edelstein

Rack - Die Webserver-Schnittstelle

Die Grundlagen des Racks sind eine einfache Konvention. Jeder Rack-kompatible Webserver ruft immer eine Aufrufmethode für ein Objekt auf, das Sie ihm geben, und liefert das Ergebnis dieser Methode. Rack gibt genau an, wie diese Aufrufmethode aussehen und wie sie zurückgegeben werden muss. Das ist Rack.

Probieren wir es einfach aus. Ich werde WEBrick als Rack-kompatiblen Webserver verwenden, aber jeder von ihnen wird es tun. Erstellen wir eine einfache Webanwendung, die eine JSON-Zeichenfolge zurückgibt. Dazu erstellen wir eine Datei namens config.ru. Die config.ru wird automatisch vom Befehlackup des Rack-Gem aufgerufen, der einfach den Inhalt der config.ru auf einem Rack-kompatiblen Webserver ausführt. Fügen wir der Datei config.ru also Folgendes hinzu:

class JSONServer
  def call(env)
    [200, {"Content-Type" => "application/json"}, ['{ "message" : "Hello!" }']]
  end
end

map '/hello.json' do
  run JSONServer.new
end

Wie in der Konvention angegeben, verfügt unser Server über eine Methode namens call, die einen Umgebungs-Hash akzeptiert und ein Array mit der Form [Status, Header, Body] zurückgibt, die der Webserver bedienen soll. Probieren wir es einfach aus, indem wir Rackup anrufen. Ein Standard-Rack-kompatibler Server, möglicherweise WEBrick oder Mongrel, wird gestartet und wartet sofort auf Anfragen.

$ rackup
[2012-02-19 22:39:26] INFO  WEBrick 1.3.1
[2012-02-19 22:39:26] INFO  ruby 1.9.3 (2012-01-17) [x86_64-darwin11.2.0]
[2012-02-19 22:39:26] INFO  WEBrick::HTTPServer#start: pid=16121 port=9292

Testen wir unseren neuen JSON-Server, indem wir entweder die URL http://localhost:9292/hello.jsonund voila locken oder besuchen :

$ curl http://localhost:9292/hello.json
{ message: "Hello!" }

Es klappt. Toll! Das ist die Basis für jedes Webframework, sei es Rails oder Sinatra. Irgendwann implementieren sie eine Aufrufmethode, arbeiten den gesamten Framework-Code durch und geben schließlich eine Antwort in der typischen Form [Status, Header, Body] zurück.

In Ruby on Rails zum Beispiel treffen die Rack-Anforderungen die ActionDispatch::Routing.MapperKlasse, die so aussieht:

module ActionDispatch
  module Routing
    class Mapper
      ...
      def initialize(app, constraints, request)
        @app, @constraints, @request = app, constraints, request
      end

      def matches?(env)
        req = @request.new(env)
        ...
        return true
      end

      def call(env)
        matches?(env) ? @app.call(env) : [ 404, {'X-Cascade' => 'pass'}, [] ]
      end
      ...
  end
end

Grundsätzlich prüft Rails, abhängig vom Env-Hash, ob eine Route übereinstimmt. In diesem Fall wird der env-Hash an die Anwendung weitergeleitet, um die Antwort zu berechnen. Andernfalls antwortet er sofort mit einem 404. Jeder Webserver, der der Rack-Schnittstellenkonvention entspricht, kann eine vollständig ausgefüllte Rails-Anwendung bereitstellen.

Middleware

Rack unterstützt auch die Erstellung von Middleware-Schichten. Sie fangen im Grunde eine Anfrage ab, machen etwas damit und geben sie weiter. Dies ist sehr nützlich für vielseitige Aufgaben.

Angenommen, wir möchten unserem JSON-Server eine Protokollierung hinzufügen, die auch misst, wie lange eine Anforderung dauert. Wir können einfach einen Middleware-Logger erstellen, der genau dies tut:

class RackLogger
  def initialize(app)
    @app = app
  end

  def call(env)
    @start = Time.now
    @status, @headers, @body = @app.call(env)
    @duration = ((Time.now - @start).to_f * 1000).round(2)

    puts "#{env['REQUEST_METHOD']} #{env['REQUEST_PATH']} - Took: #{@duration} ms"
    [@status, @headers, @body]
  end
end

Wenn es erstellt wird, speichert es sich selbst eine Kopie der eigentlichen Rack-Anwendung. In unserem Fall ist dies eine Instanz unseres JSONServers. Rack ruft automatisch die [status, headers, body]Aufrufmethode für die Middleware auf und erwartet ein Array zurück, genau wie unser JSONServer zurückgibt.

In dieser Middleware wird also der Startpunkt festgelegt, der eigentliche Aufruf des JSONServers erfolgt mit @app.call(env), der Logger gibt den Protokollierungseintrag aus und gibt schließlich die Antwort als zurück [@status, @headers, @body].

Um unser kleines Rackup.ru dazu zu bringen, diese Middleware zu verwenden, fügen Sie einen RackLogger wie folgt hinzu:

class JSONServer
  def call(env)
    [200, {"Content-Type" => "application/json"}, ['{ "message" : "Hello!" }']]
  end
end

class RackLogger
  def initialize(app)
    @app = app
  end

  def call(env)
    @start = Time.now
    @status, @headers, @body = @app.call(env)
    @duration = ((Time.now - @start).to_f * 1000).round(2)

    puts "#{env['REQUEST_METHOD']} #{env['REQUEST_PATH']} - Took: #{@duration} ms"
    [@status, @headers, @body]
  end
end

use RackLogger

map '/hello.json' do
  run JSONServer.new
end   

Starten Sie den Server neu und voila, es gibt ein Protokoll bei jeder Anfrage. Mit Rack können Sie mehrere Middlewares hinzufügen, die in der Reihenfolge aufgerufen werden, in der sie hinzugefügt wurden. Es ist einfach eine großartige Möglichkeit, Funktionen hinzuzufügen, ohne den Kern der Rack-Anwendung zu ändern.

Rack - Der Edelstein

Obwohl Rack - vor allem - eine Konvention ist, ist es auch ein Juwel, das großartige Funktionalität bietet. Eine davon haben wir bereits für unseren JSON-Server verwendet, den Befehl rampup. Aber es gibt noch mehr! Das Rack-Juwel bietet kleine Anwendungen für viele Anwendungsfälle, z. B. das Bereitstellen statischer Dateien oder sogar ganzer Verzeichnisse. Mal sehen, wie wir eine einfache Datei bereitstellen, zum Beispiel eine sehr einfache HTML-Datei unter htmls / index.html:

<!DOCTYPE HTML>
  <html>
  <head>
    <title>The Index</title>
  </head>

  <body>
    <p>Index Page</p>
  </body>
</html>

Wir möchten diese Datei möglicherweise über das Website-Stammverzeichnis bereitstellen. Fügen Sie daher Folgendes zu unserer config.ru hinzu:

map '/' do
  run Rack::File.new "htmls/index.html"
end

Wenn wir besuchen http://localhost:9292, sehen wir unsere HTML-Datei perfekt gerendert. Das war einfach, oder?

Fügen wir ein ganzes Verzeichnis von Javascript-Dateien hinzu, indem wir einige Javascript-Dateien unter / javascripts erstellen und der config.ru Folgendes hinzufügen:

map '/javascripts' do
  run Rack::Directory.new "javascripts"
end

Starten Sie den Server neu und besuchen http://localhost:9292/javascriptSie und Sie sehen eine Liste aller Javascript-Dateien, die Sie jetzt direkt von überall einschließen können.


3
Aber nicht Rack Middleware?
Rup

1
Wenn Sie nicht wissen, was ein Rack ist, wissen Sie genau, was es ist und wie Sie es verwenden, nachdem Sie diesen Blog-Beitrag gelesen haben. Sehr schön. Ironischerweise ist der Link zur offiziellen Rack-Dokumentation am Ende des Beitrags nicht mehr verfügbar!
Colin

Dein Recht, danke. Ich habe den Inhalt in den Beitrag aufgenommen und den toten Link entfernt.
Thomas Fankhauser

Ich würde sagen, dass es keine Konvention ist. Es ist eine Schnittstelle, ein Vertrag, der für ein Anfrage-Antwort-Modell gut definiert ist
Ron Klein

20

Ich hatte ein Problem damit, Rack selbst für eine gute Zeit zu verstehen. Ich habe es erst vollständig verstanden, nachdem ich daran gearbeitet habe, diesen Miniatur-Ruby-Webserver selbst herzustellen. Ich habe meine Erkenntnisse über Rack (in Form einer Geschichte) hier in meinem Blog geteilt: http://gauravchande.com/what-is-rack-in-ruby-rails

Feedback ist mehr als willkommen.


13
Von Antworten nur auf Links wird bei Stapelüberlauf abgeraten , da die Antwort unbrauchbar wird, wenn die Ressource, zu der der Link geht, in Zukunft nicht mehr verfügbar ist. Bitte fassen Sie mindestens die relevanten Punkte Ihres Blogposts zusammen und fügen Sie sie dieser Antwort hinzu.

Danke für deinen Beitrag. Ich bin ein Rails-Programmierer für Anfänger und habe das Rack-Konzept mit Ihrem klaren Beitrag verstanden.
Eduardo Ramos

Toller Blog-Beitrag. Die anderen Antworten scheinen IMO etwas komplizierter zu sein.
Clam

Was für eine großartige Erklärung. Danke, Gaurav.
Rovitulli

7

config.ru minimales lauffähiges Beispiel

app = Proc.new do |env|
  [
    200,
    {
      'Content-Type' => 'text/plain'
    },
    ["main\n"]
  ]
end

class Middleware
  def initialize(app)
    @app = app
  end

  def call(env)
    @status, @headers, @body = @app.call(env)
    [@status, @headers, @body << "Middleware\n"]
  end
end

use(Middleware)

run(app)

Laufen rackupund besuchen localhost:9292. Die Ausgabe ist:

main
Middleware

Es ist also klar, dass Middlewaredie Haupt-App umbrochen und aufgerufen wird. Daher kann es die Anforderung vorverarbeiten und die Antwort auf irgendeine Weise nachbearbeiten.

Wie unter http://guides.rubyonrails.org/rails_on_rack.html#action-dispatcher-middleware-stack erläutert , verwendet Rails Rack-Middleware für einen Großteil seiner Funktionalität, und Sie können auch eigene mit config.middleware.useFamilienmethoden hinzufügen .

Der Vorteil der Implementierung von Funktionen in einer Middleware besteht darin, dass Sie sie in jedem Rack-Framework wiederverwenden können, also in allen wichtigen Ruby-Frameworks und nicht nur in Rails.


6

Mit der Rack-Middleware können Sie eine Anfrage und Antwort filtern, die in Ihre Anwendung eingehen. Eine Middleware-Komponente befindet sich zwischen dem Client und dem Server und verarbeitet eingehende Anforderungen und ausgehende Antworten. Sie ist jedoch mehr als nur eine Schnittstelle, über die mit dem Webserver kommuniziert werden kann. Es wird verwendet, um Module, die normalerweise Ruby-Klassen sind, zu gruppieren und zu ordnen und die Abhängigkeit zwischen ihnen anzugeben. Das Rack-Middleware-Modul darf nur: - über einen Konstruktor verfügen, der die nächste Anwendung im Stapel als Parameter verwendet - auf die Aufrufmethode reagieren, die den Umgebungs-Hash als Parameter verwendet. Der von diesem Aufruf zurückgegebene Wert besteht aus folgenden Elementen: Statuscode, Umgebungs-Hash und Antworttext.


4

Ich habe Rack-Middleware verwendet, um einige Probleme zu lösen:

  1. Abfangen von JSON-Analysefehlern mit benutzerdefinierter Rack-Middleware und Zurückgeben gut formatierter Fehlermeldungen, wenn der Client fehlerhaftes JSON sendet
  2. Inhaltskomprimierung über Rack :: Deflater

In beiden Fällen wurden ziemlich elegante Korrekturen vorgenommen.


2
Diese Antwort ist zwar etwas nützlich, befasst sich jedoch nicht mit der Frage, was Rack-Middleware ist .

Auch diese ist ziemlich Link-nur Antwort ...: P
Smar

4

Was ist Rack?

Rack bietet eine minimale Schnittstelle zwischen Webservern, die Ruby- und Ruby-Frameworks unterstützen.

Mit Rack können Sie eine Rack-Anwendung schreiben.

Rack übergibt den Umgebungs-Hash (einen Hash, der in einer HTTP-Anforderung eines Clients enthalten ist und aus CGI-ähnlichen Headern besteht) an Ihre Rack-Anwendung, die die in diesem Hash enthaltenen Elemente verwenden kann, um zu tun, was sie wollen.

Was ist eine Rack-Anwendung?

Um Rack verwenden zu können, müssen Sie eine 'App' bereitstellen - ein Objekt, das auf die #callMethode mit dem Umgebungs-Hash als Parameter reagiert (normalerweise definiert als env). #callmuss ein Array mit genau drei Werten zurückgeben:

  • den Statuscode (zB '200'),
  • ein Hash von Headern ,
  • der Antworttext (der auf die Ruby-Methode reagieren muss each).

Sie können eine Rack-Anwendung schreiben, die ein solches Array zurückgibt. Diese wird von Rack innerhalb einer Antwort an Ihren Client zurückgesendet (dies ist tatsächlich eine Instanz der Klasse Rack::Response[Klicken, um zu den Dokumenten zu gelangen]).

Eine sehr einfache Rack-Anwendung:

  • gem install rack
  • Erstellen Sie eine config.ruDatei - Rack muss danach suchen.

Wir werden eine winzige Rack-Anwendung erstellen, die eine Antwort (eine Instanz von Rack::Response) zurückgibt , deren Antworttext ein Array ist, das eine Zeichenfolge enthält : "Hello, World!".

Wir werden einen lokalen Server mit dem Befehl starten rackup.

Wenn Sie den entsprechenden Port in unserem Browser besuchen, sehen Sie "Hallo Welt!" im Ansichtsfenster gerendert.

#./message_app.rb
class MessageApp
  def call(env)
    [200, {}, ['Hello, World!']]
  end
end

#./config.ru
require_relative './message_app'

run MessageApp.new

Starten Sie einen lokalen Server mit rackupund besuchen Sie localhost: 9292, und Sie sollten "Hallo Welt!" gerendert.

Dies ist keine umfassende Erklärung, aber im Wesentlichen geschieht hier, dass der Client (der Browser) über Ihren lokalen Server eine HTTP-Anforderung an Rack sendet und Rack instanziiert MessageAppund ausgeführt wird call, wobei der Umgebungs-Hash als Parameter an die Methode übergeben wird ( das envArgument).

Rack verwendet den Rückgabewert (das Array) und erstellt daraus eine Instanz von Rack::Responseund sendet diese an den Client zurück. Der Browser verwendet Magie , um "Hallo Welt!" Zu drucken. auf den Bildschirm.

Übrigens, wenn Sie sehen möchten, wie der Umgebungs-Hash aussieht, legen Sie ihn einfach puts envdarunter def call(env).

Minimal wie es ist, was Sie hier geschrieben haben, ist eine Rack-Anwendung!

Eine Rack-Anwendung mit dem Hash der eingehenden Umgebung interagieren lassen

In unserer kleinen Rack - App können wir mit dem interagieren envHash (siehe hier für mehr über das Umwelt - Hash).

Wir werden die Möglichkeit für den Benutzer implementieren, eine eigene Abfragezeichenfolge in die URL einzugeben. Daher ist diese Zeichenfolge in der HTTP-Anforderung vorhanden, die als Wert in einem der Schlüssel / Wert-Paare des Umgebungs-Hashs gekapselt ist.

Unsere Rack-App greift über den Umgebungs-Hash auf diese Abfragezeichenfolge zu und sendet sie über den Text in der Antwort an den Client (in diesem Fall unseren Browser) zurück.

Aus den Rack-Dokumenten zum Umgebungs-Hash: "QUERY_STRING: Der Teil der Anforderungs-URL, der auf das? Gefolgt wird, falls vorhanden. Kann leer sein, ist aber immer erforderlich!"

#./message_app.rb
class MessageApp
  def call(env)
    message = env['QUERY_STRING']
    [200, {}, [message]]
  end
end

Wenn Sie jetzt rackupbesuchen localhost:9292?hello( ?helloals Abfragezeichenfolge), sollte im Ansichtsfenster "Hallo" angezeigt werden.

Rack-Middleware

Wir werden:

  • fügen Sie ein Stück Rack - Middleware in unserem Code - Basis - eine Klasse: MessageSetter,
  • Der Umgebungs-Hash trifft diese Klasse zuerst und wird als Parameter übergeben : env,
  • MessageSetterfügt einen 'MESSAGE'Schlüssel in den env-Hash ein, dessen Wert 'Hello, World!'if env['QUERY_STRING']ist , wenn er leer ist; env['QUERY_STRING']wenn nicht,
  • Endlich wird es zurückkehren @app.call(env)- @appals nächste App im 'Stack' : MessageApp.

Erstens die "Langhand" -Version:

#./middleware/message_setter.rb
class MessageSetter
  def initialize(app)
    @app = app
  end

  def call(env)
    if env['QUERY_STRING'].empty?
      env['MESSAGE'] = 'Hello, World!'
    else
      env['MESSAGE'] = env['QUERY_STRING']
    end
    @app.call(env)
  end
end

#./message_app.rb (same as before)
class MessageApp
  def call(env)
    message = env['QUERY_STRING']
    [200, {}, [message]]
  end
end

#config.ru
require_relative './message_app'
require_relative './middleware/message_setter'

app = Rack::Builder.new do
  use MessageSetter
  run MessageApp.new
end

run app

Aus den Rack :: Builder-Dokumenten geht hervor , dass Rack::Builderein kleines DSL implementiert wird , um Rack-Anwendungen iterativ zu erstellen. Dies bedeutet im Grunde, dass Sie einen "Stapel" erstellen können, der aus einem oder mehreren Middlewares und einer "untersten" Anwendung besteht, an die gesendet werden soll. Alle Anfragen, die an Ihre unterste Anwendung weitergeleitet werden, werden zuerst von Ihren Middleware (s) verarbeitet.

#useGibt die Middleware an, die in einem Stapel verwendet werden soll. Es nimmt die Middleware als Argument.

Rack Middleware muss:

  • Haben Sie einen Konstruktor, der die nächste Anwendung im Stapel als Parameter verwendet.
  • Antworten Sie auf die callMethode, die den Umgebungs-Hash als Parameter verwendet.

In unserem Fall ist die 'Middleware' MessageSetter, der 'Konstruktor' die MessageSetter- initializeMethode, die 'nächste Anwendung' im Stapel MessageApp.

Also hier, wegen dem , was Rack::Buildertut unter der Haube, das appArgument von MessageSetter‚s - initializeMethode ist MessageApp.

(Machen Sie sich mit dem Kopf vertraut, bevor Sie fortfahren)

Daher gibt jede Middleware den vorhandenen Umgebungs-Hash im Wesentlichen an die nächste Anwendung in der Kette weiter. Sie haben also die Möglichkeit, diesen Umgebungs-Hash in der Middleware zu mutieren, bevor Sie ihn an die nächste Anwendung im Stapel weitergeben.

#runNimmt ein Argument, das ein Objekt ist, das auf #calleine Rack-Antwort (eine Instanz von Rack::Response) reagiert und diese zurückgibt .

Schlussfolgerungen

Mit können Rack::BuilderSie Ketten von Middlewares erstellen, und jede Anforderung an Ihre Anwendung wird von jeder Middleware nacheinander verarbeitet, bevor sie schließlich vom letzten Teil des Stapels (in unserem Fall MessageApp) verarbeitet wird. Dies ist äußerst nützlich, da verschiedene Phasen der Verarbeitung von Anforderungen getrennt werden. In Bezug auf die Trennung von Bedenken könnte es nicht viel sauberer sein!

Sie können eine 'Anforderungspipeline' erstellen, die aus mehreren Middlewares besteht, die sich mit folgenden Dingen befassen:

  • Authentifizierung
  • Genehmigung
  • Caching
  • Dekoration
  • Leistungs- und Nutzungsüberwachung
  • Ausführung (tatsächlich die Anfrage bearbeiten und eine Antwort geben)

(über den Aufzählungspunkten einer anderen Antwort in diesem Thread)

Sie werden dies häufig in professionellen Sinatra-Anwendungen sehen. Sinatra benutzt Rack! Sehen Sie hier für die Definition dessen , was Sinatra IST !

Als letzte Anmerkung config.rukönnen wir in einem Kurzschriftstil geschrieben werden, der genau die gleiche Funktionalität erzeugt (und dies ist, was Sie normalerweise sehen werden):

require_relative './message_app'
require_relative './middleware/message_setter'

use MessageSetter
run MessageApp.new

Um genauer zu zeigen, was MessageAppgerade getan wird, finden Sie hier die 'Langhand'-Version, die explizit zeigt, #calldass eine neue Instanz von Rack::Responsemit den erforderlichen drei Argumenten erstellt wird.

class MessageApp
  def call(env)
    Rack::Response.new([env['MESSAGE']], 200, {})
  end
end

Nützliche Links


1

Rack - Die Schnittstelle zwischen Web- und App-Server

Rack ist ein Ruby-Paket, das eine Schnittstelle für die Kommunikation eines Webservers mit der Anwendung bietet. Es ist einfach, Middleware-Komponenten zwischen dem Webserver und der App hinzuzufügen, um das Verhalten Ihrer Anfrage / Antwort zu ändern. Die Middleware-Komponente befindet sich zwischen dem Client und dem Server und verarbeitet eingehende Anforderungen und ausgehende Antworten.

In Laienwörtern handelt es sich im Grunde genommen nur um eine Reihe von Richtlinien, wie ein Server und eine Rails-App (oder eine andere Ruby-Web-App) miteinander kommunizieren sollen .

Um Rack zu verwenden, geben Sie eine "App" an: ein Objekt, das auf die Aufrufmethode reagiert, den Umgebungs-Hash als Parameter verwendet und ein Array mit drei Elementen zurückgibt:

  • Der HTTP-Antwortcode
  • Ein Hash von Headern
  • Der Antworttext , der auf jede Anforderung antworten muss .

Weitere Erklärungen finden Sie unter den folgenden Links.

1. https://rack.github.io/
2. https://redpanthers.co/rack-middleware/
3. https://blog.engineyard.com/2015/understanding-rack-apps-and-middleware
4. https://guides.rubyonrails.org/rails_on_rack.html#resources

In Rails haben wir config.ru als Rack-Datei. Sie können jede Rack-Datei mit dem rackupBefehl ausführen . Und der Standardport dafür ist 9292. Um dies zu testen, können Sie einfach rackupin Ihrem Rails-Verzeichnis laufen und das Ergebnis sehen. Sie können auch einen Port zuweisen, auf dem Sie ihn ausführen möchten. Der Befehl zum Ausführen der Rack-Datei an einem bestimmten Port lautet

rackup -p PORT_NUMBER

1

Bild zeigt Gestell zwischen Einhorn und Schienen

Rack ist ein Juwel, das eine einfache Schnittstelle zur abstrakten HTTP-Anforderung / Antwort bietet. Das Rack befindet sich zwischen Web-Frameworks (Rails, Sinatra usw.) und Webservern (Unicorn, Puma) als Adapter. Auf dem obigen Bild bleibt der Einhornserver völlig unabhängig von der Kenntnis von Schienen, und die Schienen wissen nichts über Einhorn. Dies ist ein gutes Beispiel für lose Kopplung und Trennung von Bedenken .

Das obige Bild stammt von diesem Rails-Konferenzgespräch im Rack https://youtu.be/3PnUV9QzB0g. Ich empfehle, es für ein tieferes Verständnis anzusehen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.