class Puma::Server

def handle_request(req, lines)

Finally, it'll return +true+ on keep-alive connections.

elsewhere, i.e. the connection has been hijacked by the Rack application.
It'll return +:async+ if the connection remains open but will be handled

that the response wasn't successful.
It'll return +false+ when the connection is closed, this doesn't mean

This is normally an instance of Puma::IOBuffer.
The second parameter +lines+ is a IO-like object unique to this thread.

the response and writes it back to +req.io+.
Takes the request +req+, invokes the Rack application to construct
def handle_request(req, lines)
  env = req.env
  client = req.io
  return false if closed_socket?(client)
  normalize_env env, req
  env[PUMA_SOCKET] = client
  if env[HTTPS_KEY] && client.peercert
    env[PUMA_PEERCERT] = client.peercert
  end
  env[HIJACK_P] = true
  env[HIJACK] = req
  body = req.body
  head = env[REQUEST_METHOD] == HEAD
  env[RACK_INPUT] = body
  env[RACK_URL_SCHEME] = default_server_port(env) == PORT_443 ? HTTPS : HTTP
  if @early_hints
    env[EARLY_HINTS] = lambda { |headers|
      begin
        fast_write client, "HTTP/1.1 103 Early Hints\r\n".freeze
        headers.each_pair do |k, vs|
          if vs.respond_to?(:to_s) && !vs.to_s.empty?
            vs.to_s.split(NEWLINE).each do |v|
              next if possible_header_injection?(v)
              fast_write client, "#{k}: #{v}\r\n"
            end
          else
            fast_write client, "#{k}: #{vs}\r\n"
          end
        end
        fast_write client, "\r\n".freeze
      rescue ConnectionError
        # noop, if we lost the socket we just won't send the early hints
      end
    }
  end
  # Fixup any headers with , in the name to have _ now. We emit
  # headers with , in them during the parse phase to avoid ambiguity
  # with the - to _ conversion for critical headers. But here for
  # compatibility, we'll convert them back. This code is written to
  # avoid allocation in the common case (ie there are no headers
  # with , in their names), that's why it has the extra conditionals.
  to_delete = nil
  to_add = nil
  env.each do |k,v|
    if k.start_with?("HTTP_") and k.include?(",") and k != "HTTP_TRANSFER,ENCODING"
      if to_delete
        to_delete << k
      else
        to_delete = [k]
      end
      unless to_add
        to_add = {}
      end
      to_add[k.tr(",", "_")] = v
    end
  end
  if to_delete
    to_delete.each { |k| env.delete(k) }
    env.merge! to_add
  end
  # A rack extension. If the app writes #call'ables to this
  # array, we will invoke them when the request is done.
  #
  after_reply = env[RACK_AFTER_REPLY] = []
  begin
    begin
      status, headers, res_body = @app.call(env)
      return :async if req.hijacked
      status = status.to_i
      if status == -1
        unless headers.empty? and res_body == []
          raise "async response must have empty headers and body"
        end
        return :async
      end
    rescue ThreadPool::ForceShutdown => e
      @events.log "Detected force shutdown of a thread, returning 503"
      @events.unknown_error self, e, "Rack app"
      status = 503
      headers = {}
      res_body = ["Request was internally terminated early\n"]
    rescue Exception => e
      @events.unknown_error self, e, "Rack app", env
      status, headers, res_body = lowlevel_error(e, env)
    end
    content_length = nil
    no_body = head
    if res_body.kind_of? Array and res_body.size == 1
      content_length = res_body[0].bytesize
    end
    cork_socket client
    line_ending = LINE_END
    colon = COLON
    http_11 = if env[HTTP_VERSION] == HTTP_11
      allow_chunked = true
      keep_alive = env.fetch(HTTP_CONNECTION, "").downcase != CLOSE
      include_keepalive_header = false
      # An optimization. The most common response is 200, so we can
      # reply with the proper 200 status without having to compute
      # the response header.
      #
      if status == 200
        lines << HTTP_11_200
      else
        lines.append "HTTP/1.1 ", status.to_s, " ",
                     fetch_status_code(status), line_ending
        no_body ||= status < 200 || STATUS_WITH_NO_ENTITY_BODY[status]
      end
      true
    else
      allow_chunked = false
      keep_alive = env.fetch(HTTP_CONNECTION, "").downcase == KEEP_ALIVE
      include_keepalive_header = keep_alive
      # Same optimization as above for HTTP/1.1
      #
      if status == 200
        lines << HTTP_10_200
      else
        lines.append "HTTP/1.0 ", status.to_s, " ",
                     fetch_status_code(status), line_ending
        no_body ||= status < 200 || STATUS_WITH_NO_ENTITY_BODY[status]
      end
      false
    end
    response_hijack = nil
    headers.each do |k, vs|
      case k.downcase
      when CONTENT_LENGTH2
        next if possible_header_injection?(vs)
        content_length = vs
        next
      when TRANSFER_ENCODING
        allow_chunked = false
        content_length = nil
      when HIJACK
        response_hijack = vs
        next
      end
      if vs.respond_to?(:to_s) && !vs.to_s.empty?
        vs.to_s.split(NEWLINE).each do |v|
          next if possible_header_injection?(v)
          lines.append k, colon, v, line_ending
        end
      else
        lines.append k, colon, line_ending
      end
    end
    if include_keepalive_header
      lines << CONNECTION_KEEP_ALIVE
    elsif http_11 && !keep_alive
      lines << CONNECTION_CLOSE
    end
    if no_body
      if content_length and status != 204
        lines.append CONTENT_LENGTH_S, content_length.to_s, line_ending
      end
      lines << line_ending
      fast_write client, lines.to_s
      return keep_alive
    end
    if content_length
      lines.append CONTENT_LENGTH_S, content_length.to_s, line_ending
      chunked = false
    elsif !response_hijack and allow_chunked
      lines << TRANSFER_ENCODING_CHUNKED
      chunked = true
    end
    lines << line_ending
    fast_write client, lines.to_s
    if response_hijack
      response_hijack.call client
      return :async
    end
    begin
      res_body.each do |part|
        next if part.bytesize.zero?
        if chunked
          fast_write client, part.bytesize.to_s(16)
          fast_write client, line_ending
          fast_write client, part
          fast_write client, line_ending
        else
          fast_write client, part
        end
        client.flush
      end
      if chunked
        fast_write client, CLOSE_CHUNKED
        client.flush
      end
    rescue SystemCallError, IOError
      raise ConnectionError, "Connection error detected during write"
    end
  ensure
    uncork_socket client
    body.close
    req.tempfile.unlink if req.tempfile
    res_body.close if res_body.respond_to? :close
    after_reply.each { |o| o.call }
  end
  return keep_alive
end