Repository: puma/puma
File: lib/puma/request.rb (Ruby)

Code before:
    # @param requests [Integer] number of inline requests handled
    # @param client [Puma::Client]
    # @return [Boolean,:async] keep-alive status or `:async`
    def prepare_response(status, headers, res_body, requests, client)
      env = client.env
      socket = client.io
      io_buffer = client.io_buffer

      return false if closed_socket?(socket)

      # Close the connection after a reasonable number of inline requests
      # if the server is at capacity and the listener has a new connection ready.
      # This allows Puma to service connections fairly when the number
      # of concurrent connections exceeds the size of the threadpool.
      force_keep_alive = requests < @max_fast_inline ||
        @thread_pool.busy_threads < @max_threads ||
        !client.listener.to_io.wait_readable(0)

      resp_info = str_headers(env, status, headers, res_body, io_buffer, force_keep_alive)

      close_body = false

      # below converts app_body into body, dependent on app_body's characteristics, and
      # resp_info[:content_length] will be set if it can be determined
      if !resp_info[:content_length] && !resp_info[:transfer_encoding] && status != 204
        if res_body.respond_to?(:to_ary) && (array_body = res_body.to_ary) && array_body.is_a?(Array)
          body = array_body
          resp_info[:content_length] = body.sum(&:bytesize)
        elsif res_body.is_a?(File) && res_body.respond_to?(:size)
          body = res_body
          resp_info[:content_length] = body.size
        elsif res_body.respond_to?(:to_path) && res_body.respond_to?(:each) &&
            File.readable?(fn = res_body.to_path)
          body = File.open fn, 'rb'
          resp_info[:content_length] = body.size
          close_body = true
        else
          body = res_body
        end
      elsif !res_body.is_a?(::File) && res_body.respond_to?(:to_path) && res_body.respond_to?(:each) &&
          File.readable?(fn = res_body.to_path)
        body = File.open fn, 'rb'
        resp_info[:content_length] = body.size
        close_body = true
      elsif !res_body.is_a?(::File) && res_body.respond_to?(:filename) && res_body.respond_to?(:each) &&
          res_body.respond_to?(:bytesize) && File.readable?(fn = res_body.filename)
        # Sprockets::Asset
        resp_info[:content_length] = res_body.bytesize unless resp_info[:content_length]
        if res_body.to_hash[:source]   # use each to return @source
          body = res_body
        else                           # avoid each and use a File object

Review comment (suggestion):
```suggestion
        if res_body.respond_to?(:to_ary) && (array_body = res_body.to_ary)
```

Code after:
    # @param requests [Integer] number of inline requests handled
    # @param client [Puma::Client]
    # @return [Boolean,:async] keep-alive status or `:async`
    def prepare_response(status, headers, res_body, requests, client)
      env = client.env
      socket = client.io
      io_buffer = client.io_buffer

      return false if closed_socket?(socket)

      # Close the connection after a reasonable number of inline requests
      # if the server is at capacity and the listener has a new connection ready.
      # This allows Puma to service connections fairly when the number
      # of concurrent connections exceeds the size of the threadpool.
      force_keep_alive = requests < @max_fast_inline ||
        @thread_pool.busy_threads < @max_threads ||
        !client.listener.to_io.wait_readable(0)

      resp_info = str_headers(env, status, headers, res_body, io_buffer, force_keep_alive)

      close_body = false

      # below converts app_body into body, dependent on app_body's characteristics, and
      # resp_info[:content_length] will be set if it can be determined
      if !resp_info[:content_length] && !resp_info[:transfer_encoding] && status != 204
        if res_body.respond_to?(:to_ary) && (array_body = res_body.to_ary)
          body = array_body
          resp_info[:content_length] = body.sum(&:bytesize)
        elsif res_body.is_a?(File) && res_body.respond_to?(:size)
          body = res_body
          resp_info[:content_length] = body.size
        elsif res_body.respond_to?(:to_path) && res_body.respond_to?(:each) &&
            File.readable?(fn = res_body.to_path)
          body = File.open fn, 'rb'
          resp_info[:content_length] = body.size
          close_body = true
        else
          body = res_body
        end
      elsif !res_body.is_a?(::File) && res_body.respond_to?(:to_path) && res_body.respond_to?(:each) &&
          File.readable?(fn = res_body.to_path)
        body = File.open fn, 'rb'
        resp_info[:content_length] = body.size
        close_body = true
      elsif !res_body.is_a?(::File) && res_body.respond_to?(:filename) && res_body.respond_to?(:each) &&
          res_body.respond_to?(:bytesize) && File.readable?(fn = res_body.filename)
        # Sprockets::Asset
        resp_info[:content_length] = res_body.bytesize unless resp_info[:content_length]
        if res_body.to_hash[:source]   # use each to return @source
          body = res_body
        else                           # avoid each and use a File object