yahns Ruby server user/dev discussion
 help / color / mirror / code / Atom feed
* [REJECT] proxy: return requested HTTP version for 1.0 responses
@ 2016-02-02  1:50 Eric Wong
  0 siblings, 0 replies; only message in thread
From: Eric Wong @ 2016-02-02  1:50 UTC (permalink / raw)
  To: yahns-public

(A work-in-progress).

Rejecting this for now, not sure if it's worth it
given how HTTP/1.0 clients tend to be able to process
Content-Length: just fine.
---
 lib/yahns/proxy_http_response.rb | 69 +++++++++++++++++++++++-----------------
 test/test_proxy_pass.rb          |  7 ++--
 2 files changed, 42 insertions(+), 34 deletions(-)

diff --git a/lib/yahns/proxy_http_response.rb b/lib/yahns/proxy_http_response.rb
index 0a7e722..8ccf20c 100644
--- a/lib/yahns/proxy_http_response.rb
+++ b/lib/yahns/proxy_http_response.rb
@@ -70,42 +70,51 @@ def proxy_response_start(res, tip, kcar, req_res)
     alive = @hs.next? && self.class.persistent_connections
     response_headers = env['yahns.proxy_pass.response_headers']
 
-    res = "HTTP/1.1 #{msg ? %Q(#{code} #{msg}) : status}\r\n".dup
-    headers.each do |key,value| # n.b.: headers is an Array of 2-element Arrays
-      case key
-      when /\A(?:Connection|Keep-Alive)\z/i
-        next # do not let some upstream headers leak through
-      when %r{\AContent-Length\z}i
-        flags |= MSG_MORE if have_body && value.to_i > 0
+    if ver = env['HTTP_VERSION']
+      zero = ver == 'HTTP/1.0'.freeze
+      res = "#{ver} #{msg ? %Q(#{code} #{msg}) : status}\r\n".dup
+      # n.b.: headers is an Array of 2-element Arrays
+      headers.each do |key,value|
+        case key
+        when /\A(?:Connection|Keep-Alive)\z/i
+          next # do not let some upstream headers leak through
+        when %r{\AContent-Length\z}i
+          next if zero
+          flags |= MSG_MORE if have_body && value.to_i > 0
+        end
+
+        # response header mapping
+        case val = response_headers[key]
+        when :ignore
+          next
+        when String
+          value = val
+        end
+
+        res << "#{key}: #{value}\r\n"
       end
 
-      # response header mapping
-      case val = response_headers[key]
-      when :ignore
-        next
-      when String
-        value = val
+      # For now, do not add a Date: header, assume upstream already did it
+      # but do not care if they did not
+      if zero
+        res << "\r\n".freeze
+      else
+        res << (alive ? "Connection: keep-alive\r\n\r\n".freeze
+                      : "Connection: close\r\n\r\n".freeze)
       end
 
-      res << "#{key}: #{value}\r\n"
+      # send the headers
+      case rv = kgio_syssend(res, flags)
+      when nil then break # all done, likely
+      when String # partial write, highly unlikely
+        flags = MSG_DONTWAIT
+        res = rv # hope the skb grows
+      when :wait_writable, :wait_readable # highly unlikely in real apps
+        wbuf = proxy_write(nil, res, alive)
+        break # keep buffering as much as possible
+      end while true
     end
 
-    # For now, do not add a Date: header, assume upstream already did it
-    # but do not care if they did not
-    res << (alive ? "Connection: keep-alive\r\n\r\n".freeze
-                  : "Connection: close\r\n\r\n".freeze)
-
-    # send the headers
-    case rv = kgio_syssend(res, flags)
-    when nil then break # all done, likely
-    when String # partial write, highly unlikely
-      flags = MSG_DONTWAIT
-      res = rv # hope the skb grows
-    when :wait_writable, :wait_readable # highly unlikely in real apps
-      wbuf = proxy_write(nil, res, alive)
-      break # keep buffering as much as possible
-    end while true
-
     rbuf = Thread.current[:yahns_rbuf]
     tip = tip.empty? ? [] : [ tip ]
 
diff --git a/test/test_proxy_pass.rb b/test/test_proxy_pass.rb
index f6e0efd..f5dfde1 100644
--- a/test/test_proxy_pass.rb
+++ b/test/test_proxy_pass.rb
@@ -371,7 +371,6 @@ def test_proxy_pass
         h10 = TCPSocket.new(host, port)
         h10.write "GET /chunky-slow-#{delay} HTTP/1.0\r\n\r\n"
         res = Timeout.timeout(60) { h10.read }
-        assert_match %r{^Connection: close\r\n}, res
         assert_match %r{^Content-Type: text/pain\r\n}, res
         assert_match %r{\r\n\r\nHI!\z}, res
         refute_match %r{^Transfer-Encoding:}, res
@@ -515,7 +514,7 @@ def check_slow_giant_body(host, port)
     assert_raises(EOFError) { loop { str << s.readpartial(400, buf) } }
     h, b = str.split(/\r\n\r\n/, 2)
     assert_equal OMFG, b
-    assert_match %r{\AHTTP/1\.1 200\b}, h
+    assert_match %r{\AHTTP/1\.0 200\b}, h
   ensure
     s.close if s
   end
@@ -576,14 +575,14 @@ def check_eof_body(host, port)
       s = TCPSocket.new(host, port)
       s.write("GET /eof-body-fast HTTP/1.0\r\n\r\n")
       res = s.read
-      assert_match %r{\AHTTP/1\.1 200 OK\r\n}, res
+      assert_match %r{\AHTTP/1\.0 200 OK\r\n}, res
       assert_match %r{\r\n\r\neof-body-fast\z}, res
       s.close
 
       s = TCPSocket.new(host, port)
       s.write("GET /eof-body-slow HTTP/1.0\r\n\r\n")
       res = s.read
-      assert_match %r{\AHTTP/1\.1 200 OK\r\n}, res
+      assert_match %r{\AHTTP/1\.0 200 OK\r\n}, res
       assert_match %r{\r\n\r\neof-body-slow\z}, res
       s.close
     end
-- 
EW


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

only message in thread, other threads:[~2016-02-02  1:50 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-02  1:50 [REJECT] proxy: return requested HTTP version for 1.0 responses Eric Wong

Code repositories for project(s) associated with this public inbox

	https://yhbt.net/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).