module Puma::Request
def fast_write_response(socket, body, io_buffer, chunked, content_length)
-
(ConnectionError)
-
Parameters:
-
chunked
(Boolean
) -- -
io_buffer
(Puma::IOBuffer
) -- contains headers -
body
(Enumerable, File
) -- the body object -
socket
(#write
) -- the response socket
def fast_write_response(socket, body, io_buffer, chunked, content_length) if body.is_a?(::File) && body.respond_to?(:read) if chunked # would this ever happen? while chunk = body.read(BODY_LEN_MAX) io_buffer.append chunk.bytesize.to_s(16), LINE_END, chunk, LINE_END end fast_write_str socket, CLOSE_CHUNKED else if content_length <= IO_BODY_MAX io_buffer.write body.read(content_length) fast_write_str socket, io_buffer.read_and_reset else fast_write_str socket, io_buffer.read_and_reset IO.copy_stream body, socket end end elsif body.is_a?(::Array) && body.length == 1 body_first = nil # using body_first = body.first causes issues? body.each { |str| body_first ||= str } if body_first.is_a?(::String) && body_first.bytesize < BODY_LEN_MAX # smaller body, write to io_buffer first io_buffer.write body_first fast_write_str socket, io_buffer.read_and_reset else # large body, write both header & body to socket fast_write_str socket, io_buffer.read_and_reset fast_write_str socket, body_first end elsif body.is_a?(::Array) # for array bodies, flush io_buffer to socket when size is greater than # IO_BUFFER_LEN_MAX if chunked body.each do |part| next if (byte_size = part.bytesize).zero? io_buffer.append byte_size.to_s(16), LINE_END, part, LINE_END if io_buffer.length > IO_BUFFER_LEN_MAX fast_write_str socket, io_buffer.read_and_reset end end io_buffer.write CLOSE_CHUNKED else body.each do |part| next if part.bytesize.zero? io_buffer.write part if io_buffer.length > IO_BUFFER_LEN_MAX fast_write_str socket, io_buffer.read_and_reset end end end # may write last body part for non-chunked, also headers if array is empty fast_write_str(socket, io_buffer.read_and_reset) unless io_buffer.length.zero? else # for enum bodies if chunked empty_body = true body.each do |part| next if part.nil? || (byte_size = part.bytesize).zero? empty_body = false io_buffer.append byte_size.to_s(16), LINE_END, part, LINE_END fast_write_str socket, io_buffer.read_and_reset end if empty_body io_buffer << CLOSE_CHUNKED fast_write_str socket, io_buffer.read_and_reset else fast_write_str socket, CLOSE_CHUNKED end else fast_write_str socket, io_buffer.read_and_reset body.each do |part| next if part.bytesize.zero? fast_write_str socket, part end end end socket.flush rescue Errno::EAGAIN, Errno::EWOULDBLOCK raise ConnectionError, SOCKET_WRITE_ERR_MSG rescue Errno::EPIPE, SystemCallError, IOError raise ConnectionError, SOCKET_WRITE_ERR_MSG end