unicorn Ruby/Rack server user+dev discussion/patches/pulls/bugs/help
 help / color / mirror / code / Atom feed
From: Jeremy Evans <code@jeremyevans.net>
To: Eric Wong <e@80x24.org>
Cc: unicorn-public@bogomips.org
Subject: Re: Support default_middleware configurator method
Date: Thu, 20 Sep 2018 17:21:58 -0700	[thread overview]
Message-ID: <20180921002158.GC89979@jeremyevans.local> (raw)
In-Reply-To: <20180919073926.fnwvgrkmszxxg5mw@dcvr>

On 09/19 07:39, Eric Wong wrote:
> Jeremy Evans <code@jeremyevans.net> wrote:
> > OK. To implement that, I modified the bin/unicorn file so -N
> > is only respected while parsing ARGV, and not while parsing
> > embedded configuration file options.
> 
> Thanks.
> 
> Unfortunately, -N on the command-line was broken by your patch.
> I fixed configurator.rb ordering (below) to pass t0300
> integration test.
> 
> Also, using a non-config.ru .rb file (TestHandler in
> test/unit/test_server.rb) was broken because of missing
> parentheses.

Sorry about both of those issues and for the delay in responding to
this.  I've included your changes in the following squashed commit,
which also includes an integration test for the default_middleware
configuration option, based on the existing integration test for
the -N option.

Thanks,
Jeremy

From fdbbcc82b838a39abdc43448490eb83d80c4f763 Mon Sep 17 00:00:00 2001
From: Jeremy Evans <code@jeremyevans.net>
Date: Thu, 13 Sep 2018 10:48:25 -0700
Subject: [PATCH] Support default_middleware configuration option

This allows for the equivalent of the
-N/--no-default_middleware command line option to be
specified in the configuration file so it doesn't
need to be specified on the command line every time
unicorn is executed.

It explicitly excludes the use of -N/--no-default_middleware
as an embedded configuration option in the rackup file, by
ignoring the options after ARGV is parsed.

In order to allow the configuration method to work, have
the lambda that Unicorn.builder returns accept two arguments.
Technically, only one argument is needed for the HttpServer
instance, but I'm guessing if the lambda accepts a single
argument, we expect that to be a rack application instead
of a lambda that returns a rack application.

The command line option option to disable default middleware
will take precedence over the unicorn configuration file option
if both are present.

For backwards compatibility, if the lambda passed to
HttpServer accepts 0 arguments, then call it without
arguments.
---
 bin/unicorn                         |  4 +++-
 lib/unicorn.rb                      |  8 ++------
 lib/unicorn/configurator.rb         | 11 +++++++++++
 lib/unicorn/http_server.rb          |  8 +++++---
 t/t0301-default-middleware-false.sh | 22 ++++++++++++++++++++++
 5 files changed, 43 insertions(+), 10 deletions(-)
 create mode 100644 t/t0301-default-middleware-false.sh

diff --git a/bin/unicorn b/bin/unicorn
index 3c5e5cb..00c8464 100755
--- a/bin/unicorn
+++ b/bin/unicorn
@@ -6,6 +6,7 @@
 ENV["RACK_ENV"] ||= "development"
 rackup_opts = Unicorn::Configurator::RACKUP
 options = rackup_opts[:options]
+set_no_default_middleware = true
 
 op = OptionParser.new("", 24, '  ') do |opts|
   cmd = File.basename($0)
@@ -60,7 +61,7 @@
 
   opts.on("-N", "--no-default-middleware",
           "do not load middleware implied by RACK_ENV") do |e|
-    rackup_opts[:no_default_middleware] = true
+    rackup_opts[:no_default_middleware] = true if set_no_default_middleware
   end
 
   opts.on("-D", "--daemonize", "run daemonized in the background") do |d|
@@ -110,6 +111,7 @@
   opts.parse! ARGV
 end
 
+set_no_default_middleware = false
 app = Unicorn.builder(ARGV[0] || 'config.ru', op)
 op = nil
 
diff --git a/lib/unicorn.rb b/lib/unicorn.rb
index b6dae36..5f2134d 100644
--- a/lib/unicorn.rb
+++ b/lib/unicorn.rb
@@ -45,12 +45,8 @@ def self.builder(ru, op)
       abort "rack and Rack::Builder must be available for processing #{ru}"
     end
 
-    # Op is going to get cleared before the returned lambda is called, so
-    # save this value so that it's still there when we need it:
-    no_default_middleware = op[:no_default_middleware]
-
     # always called after config file parsing, may be called after forking
-    lambda do ||
+    lambda do |_, server|
       inner_app = case ru
       when /\.ru$/
         raw = File.read(ru)
@@ -66,7 +62,7 @@ def self.builder(ru, op)
         pp({ :inner_app => inner_app })
       end
 
-      return inner_app if no_default_middleware
+      return inner_app unless server.default_middleware
 
       middleware = { # order matters
         ContentLength: nil,
diff --git a/lib/unicorn/configurator.rb b/lib/unicorn/configurator.rb
index f34d38b..d426edf 100644
--- a/lib/unicorn/configurator.rb
+++ b/lib/unicorn/configurator.rb
@@ -88,6 +88,9 @@ def reload(merge_defaults = true) #:nodoc:
     RACKUP[:set_listener] and
       set[:listeners] << "#{RACKUP[:host]}:#{RACKUP[:port]}"
 
+    RACKUP[:no_default_middleware] and
+      set[:default_middleware] = false
+
     # unicorn_rails creates dirs here after working_directory is bound
     after_reload.call if after_reload
 
@@ -265,6 +268,14 @@ def worker_processes(nr)
     set_int(:worker_processes, nr, 1)
   end
 
+  # sets whether to add default middleware in the development and
+  # deployment RACK_ENVs.
+  #
+  # default_middleware is only available in unicorn 5.5.0+
+  def default_middleware(bool)
+    set_bool(:default_middleware, bool)
+  end
+
   # sets listeners to the given +addresses+, replacing or augmenting the
   # current set.  This is for the global listener pool shared by all
   # worker processes.  For per-worker listeners, see the after_fork example
diff --git a/lib/unicorn/http_server.rb b/lib/unicorn/http_server.rb
index b2bbddb..62f6171 100644
--- a/lib/unicorn/http_server.rb
+++ b/lib/unicorn/http_server.rb
@@ -14,7 +14,8 @@ class Unicorn::HttpServer
   attr_accessor :app, :timeout, :worker_processes,
                 :before_fork, :after_fork, :before_exec,
                 :listener_opts, :preload_app,
-                :orig_app, :config, :ready_pipe, :user
+                :orig_app, :config, :ready_pipe, :user,
+                :default_middleware
   attr_writer   :after_worker_exit, :after_worker_ready, :worker_exec
 
   attr_reader :pid, :logger
@@ -70,6 +71,7 @@ def initialize(app, options = {})
     @app = app
     @request = Unicorn::HttpRequest.new
     @reexec_pid = 0
+    @default_middleware = true
     options = options.dup
     @ready_pipe = options.delete(:ready_pipe)
     @init_listeners = options[:listeners] ? options[:listeners].dup : []
@@ -784,12 +786,12 @@ def listener_names(listeners = LISTENERS)
   end
 
   def build_app!
-    if app.respond_to?(:arity) && app.arity == 0
+    if app.respond_to?(:arity) && (app.arity == 0 || app.arity == 2)
       if defined?(Gem) && Gem.respond_to?(:refresh)
         logger.info "Refreshing Gem list"
         Gem.refresh
       end
-      self.app = app.call
+      self.app = app.arity == 0 ? app.call : app.call(nil, self)
     end
   end
 
diff --git a/t/t0301-default-middleware-false.sh b/t/t0301-default-middleware-false.sh
new file mode 100644
index 0000000..c505f1d
--- /dev/null
+++ b/t/t0301-default-middleware-false.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+. ./test-lib.sh
+t_plan 3 "test the default_middleware false configuration option"
+
+t_begin "setup and start" && {
+	unicorn_setup
+	echo default_middleware false >> $unicorn_config
+	unicorn -D -c $unicorn_config fails-rack-lint.ru
+	unicorn_wait_start
+}
+
+t_begin "check exit status with Rack::Lint not present" && {
+	test 42 -eq "$(curl -sf -o/dev/null -w'%{http_code}' http://$listen/)"
+}
+
+t_begin "killing succeeds" && {
+	kill $unicorn_pid
+	check_stderr
+}
+
+t_done
+
-- 
2.17.1


  reply	other threads:[~2018-09-22 16:11 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-09-13 19:20 Jeremy Evans
2018-09-13 22:34 ` Eric Wong
2018-09-14  0:00   ` Jeremy Evans
2018-09-14 10:56     ` Eric Wong
2018-09-14 15:03       ` Jeremy Evans
2018-09-19  7:39         ` Eric Wong
2018-09-21  0:21           ` Jeremy Evans [this message]
2018-09-23  8:52             ` Eric Wong
2018-09-21  0:34           ` [PATCH 2/1] tests: ensure -N/--no-default-middleware not supported in config.ru Eric Wong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://yhbt.net/unicorn/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180921002158.GC89979@jeremyevans.local \
    --to=code@jeremyevans.net \
    --cc=e@80x24.org \
    --cc=unicorn-public@bogomips.org \
    --subject='Re: Support default_middleware configurator method' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

unicorn Ruby/Rack server user+dev discussion/patches/pulls/bugs/help

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://yhbt.net/unicorn-public
	git clone --mirror http://ou63pmih66umazou.onion/unicorn-public

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V1 unicorn-public unicorn-public/ https://yhbt.net/unicorn-public \
		unicorn-public@yhbt.net unicorn-public@bogomips.org mongrel-unicorn@rubyforge.org mongrel-unicorn-GrnCvJ7WPxnNLxjTenLetw@public.gmane.org
	public-inbox-index unicorn-public

Example config snippet for mirrors.
Newsgroups are available over NNTP:
	nntp://news.public-inbox.org/inbox.comp.lang.ruby.unicorn
	nntp://7fh6tueqddpjyxjmgtdiueylzoqt6pt7hec3pukyptlmohoowvhde4yd.onion/inbox.comp.lang.ruby.unicorn
 note: .onion URLs require Tor: https://www.torproject.org/

code repositories for project(s) associated with this inbox:

	../../unicorn.git

AGPL code for this site: git clone http://7fh6tueqddpjyxjmgtdiueylzoqt6pt7hec3pukyptlmohoowvhde4yd.onion/public-inbox.git