module Puma::Request

def handle_request(client, requests)

Returns:
  • (Boolean, :async) -

Parameters:
  • requests (Integer) --
  • client (Puma::Client) --
def handle_request(client, requests)
  env = client.env
  io_buffer = client.io_buffer
  socket  = client.io   # io may be a MiniSSL::Socket
  app_body = nil
  return false if closed_socket?(socket)
  if client.http_content_length_limit_exceeded
    return prepare_response(413, {}, ["Payload Too Large"], requests, client)
  end
  normalize_env env, client
  env[PUMA_SOCKET] = socket
  if env[HTTPS_KEY] && socket.peercert
    env[PUMA_PEERCERT] = socket.peercert
  end
  env[HIJACK_P] = true
  env[HIJACK] = client
  env[RACK_INPUT] = client.body
  env[RACK_URL_SCHEME] ||= default_server_port(env) == PORT_443 ? HTTPS : HTTP
  if @early_hints
    env[EARLY_HINTS] = lambda { |headers|
      begin
        unless (str = str_early_hints headers).empty?
          fast_write_str socket, "HTTP/1.1 103 Early Hints\r\n#{str}\r\n"
        end
      rescue ConnectionError => e
        @log_writer.debug_error e
        # noop, if we lost the socket we just won't send the early hints
      end
    }
  end
  req_env_post_parse env
  # A rack extension. If the app writes #call'ables to this
  # array, we will invoke them when the request is done.
  #
  env[RACK_AFTER_REPLY] ||= []
  begin
    if @supported_http_methods == :any || @supported_http_methods.key?(env[REQUEST_METHOD])
      status, headers, app_body = @thread_pool.with_force_shutdown do
        @app.call(env)
      end
    else
      @log_writer.log "Unsupported HTTP method used: #{env[REQUEST_METHOD]}"
      status, headers, app_body = [501, {}, ["#{env[REQUEST_METHOD]} method is not supported"]]
    end
    # app_body needs to always be closed, hold value in case lowlevel_error
    # is called
    res_body = app_body
    # full hijack, app called env['rack.hijack']
    return :async if client.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
    @log_writer.unknown_error e, client, "Rack app"
    @log_writer.log "Detected force shutdown of a thread"
    status, headers, res_body = lowlevel_error(e, env, 503)
  rescue Exception => e
    @log_writer.unknown_error e, client, "Rack app"
    status, headers, res_body = lowlevel_error(e, env, 500)
  end
  prepare_response(status, headers, res_body, requests, client)
ensure
  io_buffer.reset
  uncork_socket client.io
  app_body.close if app_body.respond_to? :close
  client.tempfile&.unlink
  after_reply = env[RACK_AFTER_REPLY] || []
  begin
    after_reply.each { |o| o.call }
  rescue StandardError => e
    @log_writer.debug_error e
  end unless after_reply.empty?
end