lib/reel/response.rb in reel-0.2.0 vs lib/reel/response.rb in reel-0.3.0.pre

- old
+ new

@@ -1,7 +1,12 @@ module Reel class Response + + CONTENT_LENGTH = 'Content-Length'.freeze + TRANSFER_ENCODING = 'Transfer-Encoding'.freeze + CHUNKED = 'chunked'.freeze + # Use status code tables from the Http gem STATUS_CODES = Http::Response::STATUS_CODES SYMBOL_TO_STATUS_CODE = Http::Response::SYMBOL_TO_STATUS_CODE CRLF = "\r\n" @@ -18,34 +23,23 @@ else headers = {} @body = body_or_headers end - @headers = {} - headers.each do |name, value| - name = name.to_s - key = name[Http::CANONICAL_HEADER] - key ||= canonicalize_header(name) - @headers[key] = value.to_s - end - case @body when String - @headers['Content-Length'] ||= @body.bytesize + headers[CONTENT_LENGTH] ||= @body.bytesize when IO - @headers['Content-Length'] ||= @body.stat.size + headers[CONTENT_LENGTH] ||= @body.stat.size when Enumerable - @headers['Transfer-Encoding'] ||= 'chunked' + headers[TRANSFER_ENCODING] ||= CHUNKED when NilClass else raise TypeError, "can't render #{@body.class} as a response body" end - # Prevent modification through the accessor - @headers.freeze - - # FIXME: real HTTP versioning - @version = "HTTP/1.1" + @headers = canonicalize_headers(headers) + @version = http_version end # Set the status def status=(status, reason=nil) case status @@ -69,26 +63,30 @@ case @body when String socket << @body when IO - if !defined?(JRUBY_VERSION) - IO.copy_stream(@body, socket) - else - # JRuby 1.6.7 doesn't support IO.copy_stream :( - while data = @body.read(4096) - socket << data + begin + if !defined?(JRUBY_VERSION) + IO.copy_stream(@body, socket) + else + # JRuby 1.6.7 doesn't support IO.copy_stream :( + while data = @body.read(4096) + socket << data + end end + ensure + @body.close end when Enumerable @body.each do |chunk| - chunk_header = chunk.bytesize.to_s(16) + CRLF - socket << chunk_header - socket << chunk + chunk_header = chunk.bytesize.to_s(16) + socket << chunk_header + CRLF + socket << chunk + CRLF end - socket << "0" << CRLF * 2 + socket << "0#{CRLF * 2}" end end # Convert headers into a string # FIXME: this should probably be factored elsewhere, SRP and all @@ -103,12 +101,20 @@ response_header << CRLF end private :render_header - # Transform to canonical HTTP header capitalization - def canonicalize_header(header) - header.to_s.split(/[\-_]/).map(&:capitalize).join('-') + def canonicalize_headers headers + headers.inject({}) do |headers, (header, value)| + headers.merge Http.canonicalize_header(header) => value.to_s + end.freeze end - private :canonicalize_header + private :canonicalize_headers + + def http_version + # FIXME: real HTTP versioning + "HTTP/1.1".freeze + end + private :http_version + end end