Of course, some users will prefer to bind HTTP application
servers to Unix domain sockets for better isolation and (maybe)
better performance.
---
 extras/proxy_pass.rb           |  7 +++--
 test/test_extras_proxy_pass.rb | 69 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 74 insertions(+), 2 deletions(-)

diff --git a/extras/proxy_pass.rb b/extras/proxy_pass.rb
index d435ebe..00adf18 100644
--- a/extras/proxy_pass.rb
+++ b/extras/proxy_pass.rb
@@ -112,12 +112,15 @@ class ProxyPass # :nodoc:
 
   def initialize(dest, timeout = 5)
     case dest
+    when %r{\Aunix:([^:]+)(?::(/.*))?\z}
+      path = $2
+      @sockaddr = Socket.sockaddr_un($1)
     when %r{\Ahttp://([^/]+)(/.*)?\z}
       path = $2
       host, port = $1.split(':')
       @sockaddr = Socket.sockaddr_in(port || 80, host)
     else
-      raise ArgumentError, "destination must be an HTTP URL"
+      raise ArgumentError, "destination must be an HTTP URL or unix: path"
     end
     init_path_vars(path)
     @pool = ConnPool.new
@@ -125,7 +128,7 @@ class ProxyPass # :nodoc:
   end
 
   def init_path_vars(path)
-    path ||= '$(fullpath)'
+    path ||= '$fullpath'
     # methods from Rack::Request we want:
     allow = %w(fullpath host_with_port host port url path)
     want = path.scan(/\$(\w+)/).flatten! || []
diff --git a/test/test_extras_proxy_pass.rb b/test/test_extras_proxy_pass.rb
index 8842683..5bbce73 100644
--- a/test/test_extras_proxy_pass.rb
+++ b/test/test_extras_proxy_pass.rb
@@ -1,6 +1,7 @@
 # Copyright (C) 2015 all contributors <yahns-public@yhbt.net>
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require_relative 'server_helper'
+require 'json'
 
 class TestExtrasProxyPass < Testcase
   ENV["N"].to_i > 1 and parallelize_me!
@@ -34,6 +35,74 @@ class TestExtrasProxyPass < Testcase
     server_helper_teardown
   end
 
+  def test_unix_socket_no_path
+    tmpdir = Dir.mktmpdir
+    unix_path = "#{tmpdir}/proxy_pass.sock"
+    unix_srv = UNIXServer.new(unix_path)
+    err, cfg, host, port = @err, Yahns::Config.new, @srv.addr[3], @srv.addr[1]
+    host2, port2 = @srv2.addr[3], @srv2.addr[1]
+    pid = mkserver(cfg) do
+      @srv.autoclose = @srv2.autoclose = false
+      ENV["YAHNS_FD"] = "#{@srv.fileno},#{@srv2.fileno}"
+      $LOAD_PATH.unshift "#{Dir.pwd}/extras"
+      require 'proxy_pass'
+      cfg.instance_eval do
+        app(:rack, ProxyPass.new("unix:#{unix_path}:/$fullpath")) do
+          listen "#{host}:#{port}"
+        end
+        app(:rack, ProxyPass.new("unix:#{unix_path}:/foo$fullpath")) do
+          listen "#{host2}:#{port2}"
+        end
+        stderr_path err.path
+      end
+    end
+
+    pid2 = mkserver(cfg, unix_srv) do
+      @srv.close
+      @srv2.close
+      cfg.instance_eval do
+        rapp = lambda do |env|
+          body = env.to_json
+          hdr = {
+            'Content-Length' => body.bytesize.to_s,
+            'Content-Type' => 'application/json',
+          }
+          [ 200, hdr, [ body ] ]
+        end
+        app(:rack, rapp) { listen unix_path }
+        stderr_path err.path
+      end
+    end
+    Net::HTTP.start(host, port) do |http|
+      res = http.request(Net::HTTP::Get.new('/f00'))
+      assert_equal 200, res.code.to_i
+      body = JSON.parse(res.body)
+      assert_equal '/f00', body['PATH_INFO']
+
+      res = http.request(Net::HTTP::Get.new('/f00foo'))
+      assert_equal 200, res.code.to_i
+      body = JSON.parse(res.body)
+      assert_equal '/f00foo', body['PATH_INFO']
+    end
+
+    Net::HTTP.start(host2, port2) do |http|
+      res = http.request(Net::HTTP::Get.new('/Foo'))
+      assert_equal 200, res.code.to_i
+      body = JSON.parse(res.body)
+      assert_equal '/foo/Foo', body['PATH_INFO']
+
+      res = http.request(Net::HTTP::Get.new('/Foofoo'))
+      assert_equal 200, res.code.to_i
+      body = JSON.parse(res.body)
+      assert_equal '/foo/Foofoo', body['PATH_INFO']
+    end
+  ensure
+    quit_wait(pid)
+    quit_wait(pid2)
+    unix_srv.close if unix_srv
+    FileUtils.rm_rf(tmpdir) if tmpdir
+  end
+
   def test_proxy_pass
     err, cfg, host, port = @err, Yahns::Config.new, @srv.addr[3], @srv.addr[1]
     host2, port2 = @srv2.addr[3], @srv2.addr[1]
-- 
EW


Reply via email to