i want to try out a simple rack middleware "hello world", but i seem to get stuck. it looks like the main sytax changed, since some examples use this code:
require 'rack/utils'
class FooBar
def initialize(app)
@app = app
end
def call(env)
status, headers, body = @app.call(env)
body.body << "\nHi from #{self.class}"
[status, headers, body]
end
end
produces an error:
undefined method `<<' for #<ActionDispatch::Response:0x103f07c48>
even when i look at other codes out there, i cannot seem to get them running with rails 3.0.3.
here are my concrete questions:
thanks a lot in advance!
The middleware component sits between the client and the server, processing inbound requests and outbound responses. In layman words, It is basically just a set of guidelines for how a server and a Rails app (or any other Ruby web app) should talk to each other.
One useful piece of middleware is Rack::Auth::Basic, which can be used to protect any Rack app with HTTP basic authentication. It’s really lightweight and is helpful for protecting little bits of an application. For example, Ryan Bates uses it to protect a Resque server in a Rails app in this episode of Railscasts.
To get "Hello World" from Rails, we need to create at minimum a controller and a view . A controller is needed to receive requests for the application. Routing decides which controller receives which requests.
So basically Rails checks, dependent on the env hash if any route matches. If so it passes the env hash on to the application to compute the response, otherwise it immediately responds with a 404. So any webserver that is is compliant with the rack interface convention, is able to serve a fully blown Rails application.
This should do what you want it to:
# in config/application.rb
config.middleware.use 'FooBar'
# in config/initializers/foo_bar.rb
class FooBar
def initialize(app)
@app = app
end
def call(env)
status, headers, response = @app.call(env)
[status, headers, response.body << "\nHi from #{self.class}"]
end
end
Be advised, that on just about every other request (at least on Rails 3.0.3), this will fail due to another middleware (Rack::Head) because it sends an empty request when content is unchanged. We are in this example depending on being able to call response.body, but in fact, the last member of the array can be anything that responds to .each.
Ryan Bates goes over Rack pretty well here:
http://asciicasts.com/episodes/151-rack-middleware
http://railscasts.com/episodes/151-rack-middleware
And the official Rails guide is pretty good too:
http://guides.rubyonrails.org/rails_on_rack.html
And of course the official Rack spec:
http://rack.rubyforge.org/doc/SPEC.html
Rails 3.2.12+:
previous answer does not work for Rails 3.2.12+
This one does:
# in config/application.rb
config.middleware.use 'FooBar'
# in config/initializers/foo_bar.rb
class FooBar
def initialize(app)
@app = app
end
def call(env)
status, headers, response = @app.call(env)
response.body += "\nHi from #{self.class}"
# response.body << "..." WILL NOT WORK
[status, headers, response]
end
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With