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