about summary refs log tree commit homepage
path: root/lib
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2016-11-29 03:30:02 +0000
committerEric Wong <e@80x24.org>2016-11-29 21:01:54 +0000
commit7fe9d585056ea5002cd789d70c3ea4bd5000759c (patch)
treeb211b22183dd66e532f1d26cf3bb3c09c404e800 /lib
parent6e299e20c55aa8cc63597adf90ae4d370c086b83 (diff)
downloadyahns-7fe9d585056ea5002cd789d70c3ea4bd5000759c.tar.gz
We still need to iterate through all response headers to support
response-only Rack hijacking.  Previously, we only supported
full hijacking on so-called "HTTP/0.9" clients.

n.b. This diff will be easier to read with the
     -b/--ignore-space-change option of git-diff(1) or GNU diff(1)
Diffstat (limited to 'lib')
-rw-r--r--lib/yahns/http_response.rb114
1 files changed, 56 insertions, 58 deletions
diff --git a/lib/yahns/http_response.rb b/lib/yahns/http_response.rb
index e2fc940..a31ab70 100644
--- a/lib/yahns/http_response.rb
+++ b/lib/yahns/http_response.rb
@@ -131,68 +131,66 @@ module Yahns::HttpResponse # :nodoc:
     term = false
     hdr_only, chunk_ok = opt
 
-    if @hs.headers?
-      code = status.to_i
-      hdr_only ||= Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include?(code)
-      msg = Rack::Utils::HTTP_STATUS_CODES[code]
-      buf = "#{response_start}#{msg ? %Q(#{code} #{msg}) : status}\r\n" \
-            "Date: #{httpdate}\r\n".dup
-      headers.each do |key, value|
-        case key
-        when %r{\ADate\z}i
-          next
-        when %r{\AContent-Range\z}i
-          if %r{\Abytes (\d+)-(\d+)/\d+\z} =~ value
-            offset = $1.to_i
-            count = $2.to_i - offset + 1
-          end
-          kv_str(buf, key, value)
-        when %r{\AConnection\z}i
-          # allow Rack apps to tell us they want to drop the client
-          alive = false if value =~ /\bclose\b/i
-        when %r{\AContent-Length\z}i
-          term = true
-          clen = value.to_i
-          flags |= MSG_MORE if clen > 0 && !hdr_only
-          kv_str(buf, key, value)
-        when %r{\ATransfer-Encoding\z}i
-          term = true if value =~ /\bchunked\b/i
-          kv_str(buf, key, value)
-        when "rack.hijack"
-          hijack = value
-        else
-          kv_str(buf, key, value)
+    code = status.to_i
+    hdr_only ||= Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include?(code)
+    msg = Rack::Utils::HTTP_STATUS_CODES[code]
+    buf = "#{response_start}#{msg ? %Q(#{code} #{msg}) : status}\r\n" \
+          "Date: #{httpdate}\r\n".dup
+    headers.each do |key, value|
+      case key
+      when %r{\ADate\z}i
+        next
+      when %r{\AContent-Range\z}i
+        if %r{\Abytes (\d+)-(\d+)/\d+\z} =~ value
+          offset = $1.to_i
+          count = $2.to_i - offset + 1
         end
-      end
-      count ||= clen
-
-      if !term && chunk_ok
+        kv_str(buf, key, value)
+      when %r{\AConnection\z}i
+        # allow Rack apps to tell us they want to drop the client
+        alive = false if value =~ /\bclose\b/i
+      when %r{\AContent-Length\z}i
         term = true
-        body = Yahns::ChunkBody.new(body, opt)
-        buf << "Transfer-Encoding: chunked\r\n".freeze
+        clen = value.to_i
+        flags |= MSG_MORE if clen > 0 && !hdr_only
+        kv_str(buf, key, value)
+      when %r{\ATransfer-Encoding\z}i
+        term = true if value =~ /\bchunked\b/i
+        kv_str(buf, key, value)
+      when "rack.hijack"
+        hijack = value
+      else
+        kv_str(buf, key, value)
       end
-      alive &&= term
-      buf << (alive ? "Connection: keep-alive\r\n\r\n".freeze
-                    : "Connection: close\r\n\r\n".freeze)
-      case rv = kgio_syssend(buf, flags)
-      when nil # all done, likely
-        buf.clear
-        buf = nil # recycle any memory we used ASAP
-        break
-      when String
-        flags = MSG_DONTWAIT
-        buf = rv # unlikely, hope the skb grows
-      when :wait_writable, :wait_readable # unlikely
-        if self.class.output_buffering
-          alive = hijack ? hijack : alive
-          rv = response_header_blocked(buf, body, alive, offset, count)
-          body = nil # ensure we do not close body in ensure
-          return rv
-        else
-          response_wait_write(rv) or return :close
-        end
-      end while true
     end
+    count ||= clen
+
+    if !term && chunk_ok
+      term = true
+      body = Yahns::ChunkBody.new(body, opt)
+      buf << "Transfer-Encoding: chunked\r\n".freeze
+    end
+    alive &&= term
+    buf << (alive ? "Connection: keep-alive\r\n\r\n".freeze
+                  : "Connection: close\r\n\r\n".freeze)
+    case rv = kgio_syssend(buf, flags)
+    when nil # all done, likely
+      buf.clear
+      buf = nil # recycle any memory we used ASAP
+      break
+    when String
+      flags = MSG_DONTWAIT
+      buf = rv # unlikely, hope the skb grows
+    when :wait_writable, :wait_readable # unlikely
+      if self.class.output_buffering
+        alive = hijack ? hijack : alive
+        rv = response_header_blocked(buf, body, alive, offset, count)
+        body = nil # ensure we do not close body in ensure
+        return rv
+      else
+        response_wait_write(rv) or return :close
+      end
+    end while @hs.headers?
 
     return response_hijacked(hijack) if hijack
     return http_response_done(alive) if hdr_only