From 1e4c18d895cde0af92e9286cfda52b4c10bb0488 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Fri, 5 Aug 2022 02:36:13 +1200 Subject: Allow `Rack::Builder#run` to take a block instead of an argument. (#1942) * Raise ArgumentError if both app and block given. --- CHANGELOG.md | 1 + lib/rack/builder.rb | 34 +++++++++++++++++++++++++++------- test/spec_builder.rb | 7 +++++++ 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b0d96ca..076783e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ All notable changes to this project will be documented in this file. For info on - The RFC 7239 Forwarded header is now supported and considered by default when looking for information on forwarding, falling back to the X-Forwarded-* headers. `Rack::Request.forwarded_priority` accessor has been added for configuring the priority of which header to check. ([#1423](https://github.com/rack/rack/issues/1423), [@jeremyevans]) - Allow response headers to contain array of values. ([#1598](https://github.com/rack/rack/issues/1598), [@ioquatix]) - Support callable body for explicit streaming support and clarify streaming response body behaviour. ([#1745](https://github.com/rack/rack/pull/1745), [@ioquatix], [#1748](https://github.com/rack/rack/pull/1748), [@wjordan]) +- Allow `Rack::Builder#run` to take a block instead of an argument. ([#1942](https://github.com/rack/rack/pull/1942), [@ioquatix]) ### Changed diff --git a/lib/rack/builder.rb b/lib/rack/builder.rb index fa5e876f..6d40b534 100644 --- a/lib/rack/builder.rb +++ b/lib/rack/builder.rb @@ -157,22 +157,42 @@ module Rack ruby2_keywords(:use) if respond_to?(:ruby2_keywords, true) # :nocov: - # Takes an argument that is an object that responds to #call and returns a Rack response. - # The simplest form of this is a lambda object: + # Takes a block or argument that is an object that responds to #call and + # returns a Rack response. + # + # You can use a block: + # + # run do |env| + # [200, { "content-type" => "text/plain" }, ["Hello World!"]] + # end + # + # You can also provide a lambda: # # run lambda { |env| [200, { "content-type" => "text/plain" }, ["OK"]] } # - # However this could also be a class: + # You can also provide a class instance: # # class Heartbeat - # def self.call(env) + # def call(env) # [200, { "content-type" => "text/plain" }, ["OK"]] # end # end # - # run Heartbeat - def run(app) - @run = app + # run Heartbeat.new + # + # It could also be a module: + # + # module HelloWorld + # def call(env) + # [200, { "content-type" => "text/plain" }, ["Hello World"]] + # end + # end + # + # run HelloWorld + def run(app = nil, &block) + raise ArgumentError, "Both app and block given!" if app && block_given? + + @run = app || block end # Takes a lambda or block that is used to warm-up the application. This block is called diff --git a/test/spec_builder.rb b/test/spec_builder.rb index 52bdf76c..6ca28477 100644 --- a/test/spec_builder.rb +++ b/test/spec_builder.rb @@ -34,6 +34,13 @@ describe Rack::Builder do Rack::Lint.new Rack::Builder.new(&block).to_app end + it "supports run with block" do + app = builder_to_app do + run {|env| [200, { "content-type" => "text/plain" }, ["OK"]]} + end + Rack::MockRequest.new(app).get("/").body.to_s.must_equal 'OK' + end + it "supports mapping" do app = builder_to_app do map '/' do |outer_env| -- cgit v1.2.3-24-ge0c7