dumping ground for random patches and texts
 help / color / mirror / Atom feed
* [PATCH] WIP rack_proxy1
@ 2017-03-28  1:16 Eric Wong
  0 siblings, 0 replies; only message in thread
From: Eric Wong @ 2017-03-28  1:16 UTC (permalink / raw)
  To: spew

untested!
---
 lib/yahns/proxy_pass.rb  |  3 ++
 lib/yahns/rack_proxy1.rb | 86 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 89 insertions(+)
 create mode 100644 lib/yahns/rack_proxy1.rb

diff --git a/lib/yahns/proxy_pass.rb b/lib/yahns/proxy_pass.rb
index 0ada4a6..15be710 100644
--- a/lib/yahns/proxy_pass.rb
+++ b/lib/yahns/proxy_pass.rb
@@ -18,6 +18,9 @@
 class Yahns::ProxyPass # :nodoc:
   attr_reader :proxy_buffering, :response_headers
 
+  # only used by yahns/rack_proxy1:
+  attr_accessor :worker_processes
+
   def initialize(dest, opts = {})
     case dest
     when %r{\Aunix:([^:]+)(?::(/.*))?\z}
diff --git a/lib/yahns/rack_proxy1.rb b/lib/yahns/rack_proxy1.rb
new file mode 100644
index 0000000..fdd474e
--- /dev/null
+++ b/lib/yahns/rack_proxy1.rb
@@ -0,0 +1,86 @@
+# -*- encoding: binary -*-
+# Copyright (C) 2017 all contributors <yahns-public@yhbt.net>
+# License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
+# frozen_string_literal: true
+require_relative 'rack' # require 'yahns/rack'
+require_relative 'proxy_pass'
+require 'socket'
+
+# Basically, a lazy way to setup ProxyPass to hand off some (or all)
+# requests to a simple, buggy-code tolerant HTTP server backend.
+class Yahns::RackProxy1 < Yahns::Rack # :nodoc:
+
+  # the key is the destination returned by the top-level config.ru
+  # and the value is a Yahns::ProxyPass Rack app.
+  # (default: PROXY_ALL).
+  # {
+  #   :pass => Yahns::ProxyPass,
+  #   :alt => Yahns::ProxyPass,
+  #   ...
+  # }
+  attr_reader :proxy_pass_map
+
+  # By default, proxy all requests by using the :pass return value
+  # Users can selectively process requests for non-buggy code in
+  # the core yahns processes.
+  PROXY_ALL = lambda { |env| :pass } # :nodoc:
+
+  def initialize(ru = proxy_all, opts = {})
+    # common options to be shared by all ProxyPass instances
+    gppopts = {}
+    [ :response_headers, :proxy_buffering ].each { |f| gppopts[f] = opts[f] }
+
+    pass = opts[:pass]
+    pass = { pass: pass } if String === pass
+    @proxy_pass_map = pass = pass.dup
+
+    # setup each backend:
+    pass.each do |key, ppopts|
+      ppopts = gppopts.merge(ppopts || {})
+      host = ppopts.delete(:host) || '127.0.0.1'
+
+      # nope, no UNIXServer support, maybe not worth it do deal
+      # with FS perms in containers.
+      srv = TCPServer.new(host, 0) # 0: bind random port
+      srv.setsockopt(:SOL_SOCKET, :SO_KEEPALIVE, 1)
+      srv.setsockopt(:IPPROTO_TCP, :TCP_NODELAY, 1)
+
+      # Deferring accepts slows down core yahns, but it's useful for
+      # less-sophisticated upstream (backend) servers:
+      Socket.const_defined?(:TCP_DEFER_ACCEPT) and
+        srv.setsockopt(:IPPROTO_TCP, :TCP_DEFER_ACCEPT, 1)
+
+      # Should we bother with SO_SNDBUF, SO_RCVBUF?  Seems largely
+      # unused in other servers and unused code is bloat...
+
+      srv.listen(ppopts.delete(:backlog) || 1024)
+      dest = "http://#{host}:#{srv.addr[1]}/"
+      ppass = Yahns::ProxyPass.new(dest, ppopts)
+      ppass.worker_processes = nr
+      pass[key] = ppass
+    end
+    super(ru, opts) # Yahns::Rack#initialize
+  end
+
+  def build_app!
+    super # Yahns::Rack#build_app!
+    proxy_app = @app
+
+    # wrap the (possibly-)user-supplied app
+    @app = lambda do |env|
+      res = proxy_app.call(env)
+
+      Array === res and return res  # standard Rack response
+
+      proxy_pass = @proxy_pass_map[res] and return proxy_pass.call(env)
+
+      logger = env['rack.logger'] and
+        logger.error("proxy app returned unhandled response: #{res.inspect}")
+
+      [ 500, [ %w(Content-Type text/plain) ], [] ]
+    end
+  end
+end
+
+# register ourselves
+Yahns::Config::APP_CLASS[:rack_proxy1] = Yahns::RackProxy1
-- 
EW


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2017-03-28  1:16 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-28  1:16 [PATCH] WIP rack_proxy1 Eric Wong

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).