yahns Ruby server user/dev discussion
 help / color / mirror / code / Atom feed
From: Eric Wong <e@80x24.org>
To: yahns-public@yhbt.net
Subject: [PATCH 4/3] set HTTPS and rack.url_scheme in Rack env as appropriate
Date: Fri, 12 Feb 2016 04:05:49 +0000	[thread overview]
Message-ID: <20160212040549.GA3901@dcvr.yhbt.net> (raw)
In-Reply-To: <20160212014713.32163-1-e@80x24.org>

Eric Wong <e@80x24.org> wrote:
> Things like rack.url_scheme, SERVER_NAME, SERVER_PORT, etc...
> will all need to be set properly.

SERVER_NAME and SERVER_PORT will be set inside the unicorn HTTP
parser based on the value of the Host: header

-----------8<-----------
Subject: [PATCH] set HTTPS and rack.url_scheme in Rack env as appropriate

env['HTTPS'] is not documented in rack SPEC, but appears to be
used by Rack::Request since 2010[*].  Also, set rack.url_scheme
as documented by rack SPEC.

[*] - commit 4defbe5d7c07b3ba721ff34a8ff59fde480a4a9f
      ("Improves performance by lazy loading the session.")
---
 lib/yahns/http_context.rb |  2 +-
 lib/yahns/server.rb       |  3 +++
 test/test_ssl.rb          | 43 +++++++++++++++++++++++++++++++++++--------
 3 files changed, 39 insertions(+), 9 deletions(-)

diff --git a/lib/yahns/http_context.rb b/lib/yahns/http_context.rb
index 10be062..c02eefd 100644
--- a/lib/yahns/http_context.rb
+++ b/lib/yahns/http_context.rb
@@ -17,7 +17,7 @@ module Yahns::HttpContext # :nodoc:
   attr_accessor :qegg
   attr_accessor :queue # set right before spawning acceptors
   attr_reader :app
-  attr_reader :app_defaults
+  attr_accessor :app_defaults
   attr_writer :input_buffer_tmpdir
   attr_accessor :output_buffer_tmpdir
 
diff --git a/lib/yahns/server.rb b/lib/yahns/server.rb
index 09ddbef..d6a03f3 100644
--- a/lib/yahns/server.rb
+++ b/lib/yahns/server.rb
@@ -382,6 +382,9 @@ def fdmap_init
       ctx.__send__(:include, l.expire_mod)
       if ssl_ctx = opts[:ssl_ctx]
         ctx.__send__(:include, Yahns::OpenSSLClient)
+        env = ctx.app_defaults = ctx.app_defaults.dup
+        env['HTTPS'] = 'on' # undocumented, but Rack::Request uses this
+        env['rack.url_scheme'] = 'https'
 
         # call OpenSSL::SSL::SSLContext#setup explicitly here to detect
         # errors and avoid race conditions.  We avoid calling this in the
diff --git a/test/test_ssl.rb b/test/test_ssl.rb
index 172d8e4..fe7e09e 100644
--- a/test/test_ssl.rb
+++ b/test/test_ssl.rb
@@ -63,12 +63,21 @@ def srv_ctx
 
   def test_ssl_basic
     err, cfg, host, port = @err, Yahns::Config.new, @srv.addr[3], @srv.addr[1]
+    insecure = TCPServer.new(ENV["TEST_HOST"] || "127.0.0.1", 0)
     ctx = srv_ctx
     raw = File.read(__FILE__)
     pid = mkserver(cfg) do
+      ENV["YAHNS_FD"] += ",#{insecure.fileno.to_s}"
       cfg.instance_eval do
         ru = lambda do |env|
-          case env['PATH_INFO']
+          case path_info = env['PATH_INFO']
+          when '/rack.url_scheme', '/HTTPS'
+            s = env[path_info[1..-1]] # remove leading slash
+            s = s.inspect if s.nil?
+            [ 200, {
+                'Content-Length' => s.bytesize.to_s,
+                'Content-Type'=>'text/plain',
+              }, [ s ] ]
           when '/static'
             f = File.open(__FILE__)
             [ 200, {
@@ -80,19 +89,36 @@ def test_ssl_basic
             [ 200, {'Content-Length'=>'2'}, ['HI'] ]
           end
         end
-        app(:rack, ru) { listen "#{host}:#{port}", ssl_ctx: ctx }
+        app(:rack, ru) {
+          listen "#{host}:#{port}", ssl_ctx: ctx
+          listen "#{insecure.addr[3]}:#{insecure.addr[1]}"
+        }
         logger(Logger.new(err.path))
       end
     end
     client = ssl_client(host, port)
-    client.write("GET / HTTP/1.1\r\nHost: example.com\r\n\r\n")
     buf = ''.dup
-    Timeout.timeout(60) do
-      buf << client.readpartial(111) until buf =~ /HI\z/
+    { '/' => 'HI',
+      '/rack.url_scheme' => 'https',
+      '/HTTPS' => 'on'
+    }.each do |path, exp|
+      client.write("GET #{path} HTTP/1.1\r\nHost: example.com\r\n\r\n")
+      buf.clear
+      re = /#{Regexp.escape(exp)}\z/
+      Timeout.timeout(60) do
+        buf << client.readpartial(111) until buf =~ re
+      end
+      head, body = buf.split("\r\n\r\n", 2)
+      assert_equal exp, body
+      assert_match %r{\AHTTP/1\.\d 200 OK\r\n}, head
+    end
+
+    Net::HTTP.start(insecure.addr[3], insecure.addr[1]) do |h|
+      res = h.get('/rack.url_scheme')
+      assert_equal 'http', res.body
+      res = h.get('/HTTPS')
+      assert_equal 'nil', res.body
     end
-    head, body = buf.split("\r\n\r\n", 2)
-    assert_equal "HI", body
-    assert_match %r{\AHTTP/1\.\d 200 OK\r\n}, head
 
     # read static file
     client.write("GET /static HTTP/1.1\r\nHost: example.com\r\n\r\n")
@@ -109,6 +135,7 @@ def test_ssl_basic
     assert_equal "HI", body
     assert_match %r{\AHTTP/1\.\d 200 OK\r\n}, head
   ensure
+    insecure.close if insecure
     client.close if client
     quit_wait(pid)
   end
-- 
EW

  parent reply	other threads:[~2016-02-12  4:05 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-02-12  1:47 [PATCH 0/3] TLS fixes Eric Wong
2016-02-12  1:47 ` [PATCH 1/3] acceptor: all subclasses of TCPServer use TCP_INFO Eric Wong
2016-02-12  1:47 ` [PATCH 2/3] properly emulate sendfile for OpenSSL sockets Eric Wong
2016-02-12  1:47 ` [PATCH 3/3] avoid race conditions in OpenSSL::SSL::SSLContext#setup Eric Wong
2016-02-12  4:05 ` Eric Wong [this message]
2016-02-13 22:50 ` [PATCH 5/3] proxy_pass: pass X-Forwarded-Proto through 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/yahns/README

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

  git send-email \
    --in-reply-to=20160212040549.GA3901@dcvr.yhbt.net \
    --to=e@80x24.org \
    --cc=yahns-public@yhbt.net \
    /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
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this inbox:

	../../yahns.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).