

Explaining Rack — desugaring Rack::Builder DSL
source link: https://blog.arkency.com/explaining-rack-desugaring-rack-builder-dsl/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Explaining Rack — desugaring Rack::Builder DSLHi, weʼre arkency 👋
Yesterday I wrote a post highlighting Basic Auth and how can we protect Rack applications mounted in Rails with it.
Today when discussing some ideas from this post with my colleague, our focus immediately shifted to Rack::Builder
.
On one hand Rack interface is simple, fairly constrained and well described in spec. And ships with a linter to help your Rack apps and middleware pass this compliance.
A Rack application is a Ruby object (not a class) that responds to call. It takes exactly one argument, the environment and returns an Array of exactly three values: The status, the headers, and the body.
class HelloWorld
def call(env)
[200, {"Content-Type" => "text/plain"}, ["Hello world!"]]
end
end
On the other hand your first exposure to Rack is usually via config.ru
in Rails application:
# This file is used by Rack-based servers to start the application.
require_relative "config/environment"
run Rails.application
Behind the scenes, this file is eventually passed to Rack::Builder
. It is a convenient DSL to compose Rack application out of other Rack applications. In yesterday’s blogpost we’ve seen it being used directly:
Rack::Builder.new do
use Rack::Auth::Basic do |username, password|
ActiveSupport::SecurityUtils.secure_compare(::Digest::SHA256.hexdigest(username), ::Digest::SHA256.hexdigest(ENV.fetch("DEV_UI_USERNAME"))) &
ActiveSupport::SecurityUtils.secure_compare(::Digest::SHA256.hexdigest(password), ::Digest::SHA256.hexdigest(ENV.fetch("DEV_UI_PASSWORD")))
end
run Sidekiq::Web
end
Whether you use Rack::Builder
directly or via rackup files, you’re immediately associating Rack with the use
and run
DSL.
And that triggered an honest question from my colleague — how does this DSL relate to that rather simple Rack interface?
To add even more nuance, some Rack apps are called a middleware. What is a middleware? In simple words — it’s a Rack application that wraps another Rack application. It may affect the input passed to the wrapped app. Or it may affect the output if it.
An example of a middleware that makes everything sound more dramatic:
class Dramatize
def initialize(app)
@app = app
end
def call(env)
status, headers, body = @app.call(env)
[status, headers, body.map { |x| "#{x}111one!1" }]
end
end
A composition of such middleware and our previous sample HelloWorld
application with config.ru
would look like this:
# config.ru
class HelloWorld
# omitted for brevity
end
class Dramatize
# omitted for brevity
end
use Dramatize
run HelloWorld.new
When executed, it would return very dramatic greeting:
$ bundle exec rackup config.ru
* Listening on http://127.0.0.1:9292
* Listening on http://[::1]:9292
Use Ctrl-C to stop
$ curl localhost:9292
Hello world!111one!1⏎
Now back to the question that started it all:
How does this DSL relate to that rather simple Rack interface?
The last example of composition via Rack::Builder
can be rewritten to avoid some of the DSL:
# config.ru
run Dramatize.new(HelloWorld.new)
A single run
is needed to tell a Ruby application server what is our Rack application that we’d like to run. The use of use
is on the other hand just optional.
If this post got you curious on Rack, a fun way to learn more about it is to check the code of each middleware powering your Rails application:
$ bin/rails middleware
use Webpacker::DevServerProxy
use Honeybadger::Rack::UserInformer
use Honeybadger::Rack::UserFeedback
use Honeybadger::Rack::ErrorNotifier
use Rack::Cors
use ActionDispatch::HostAuthorization
use Rack::Sendfile
use ActionDispatch::Static
use ActionDispatch::Executor
use ActiveSupport::Cache::Strategy::LocalCache::Middleware
use Rack::Runtime
use Rack::MethodOverride
use ActionDispatch::RequestId
use ActionDispatch::RemoteIp
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use ActionDispatch::DebugExceptions
use ActionDispatch::ActionableExceptions
use ActionDispatch::Reloader
use ActionDispatch::Callbacks
use ActionDispatch::Cookies
use ActionDispatch::Session::CookieStore
use ActionDispatch::Flash
use ActionDispatch::ContentSecurityPolicy::Middleware
use ActionDispatch::PermissionsPolicy::Middleware
use Rack::Head
use Rack::ConditionalGet
use Rack::ETag
use Rack::TempfileReaper
use Warden::Manager
use Rack::Deflater
use RailsEventStore::Middleware
run MyApp::Application.routes
Happy learning!
Now, a plug 🔌. This post is a part of #5days5blogposts challenge on ARKADEMY.DEV.
In this challenge we encourage you to publish five blogposts in five subsequent days. We help you generate topics to write about, structure the content and review the final effect. You get the support from our community of teachers and learners on Discord.
Join ARKADEMY.DEV now to start your blogging journey!
Recommend
-
99
作为 Rails 开发者,基本上每天都与 Rails 的各种 API 以及数据库打交道,Rails 的世界虽然非常简洁,不过其内部的实现还是很复杂的,很多刚刚接触 Rails 的开发者可能都不知道 Rails 其实就是一个 Rack 应用,在这一系列的文章中,我们会分别介绍 Rack 以及一些常...
-
17
exadata Extending an Exadata Eighth Rack to a Quarter Rack Svetoslav Gyurov...
-
16
Introduction This tutorial demonstrates how to deploy a Ruby web app using the Sinatra framework using uWSGI and nginx as the web server...
-
18
Troubleshooting IPv6 badness to certain hosts in a rack IPv6 is generally a good thing to have working on your network. However, getting there may expose a bunch of problems in the infrastructure. This story is about one of them...
-
10
An Enigma, unikernels booting on RISC-V, a rack encased in liquid. OH MY. Sunday, March 17, 2019 · 4 min read I have written a bit about how I am spending my time while being unemployed and I thought I would continue....
-
15
Contributor wabain commented
-
14
Conversation Member
-
15
Copy link Member scottmcm commented...
-
8
Copy link Contributor notriddle ...
-
11
Copy link Contributor estebank ...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK