Falcon HTTP Server

repository·main·Indexed 25 days ago

https://github.com/socketry/falcon

A high-performance, Rack-compatible HTTP server for Ruby that utilizes fibers to handle concurrent requests without blocking the server process. Falcon supports HTTP/1 and HTTP/2 and is designed to replace traditional stacks like Nginx+Passenger or Puma. It includes features such as a process supervisor for memory leak detection, support for multi-protocol endpoints via NamedEndpoints, TLS client certificate verification, and request pushback using HTTP 429.

Tokens
14.7K
Snippets
57
Records
110
Agent score
83%

What's inside Falcon

  1. Overview of Falcon HTTP Server

    main

    Falcon is a multi-process, multi-fiber Rack-compatible HTTP server. It is built on top of async, async-container, and async-http.

    Key features include:

    • Fiber-based concurrency: Each request is executed within a lightweight fiber, allowing requests to block on up-stream requests without stalling the entire server process.
    • Native Protocol Support: Supports both HTTP/1 and HTTP/2 natively.
    • Rack Compatibility: Works with existing Ruby web applications and frameworks like Rails.
    • Scalability: Uses a multi-process and multi-fiber architecture for high performance.
  2. Understand the Falcon request lifecycle

    main

    When running falcon serve, the following lifecycle occurs:

    1. Controller Initialization: Falcon creates a Falcon::Controller::Serve instance.
    2. Endpoint Binding: The controller binds to a specified endpoint (such as a local Unix socket or a TCP network socket).
    3. Worker Spawning: Worker threads or processes are spawned and receive the bound endpoint to start accepting connections.
    4. Application Loading: Each worker loads a copy of your Rack application.
    5. Rack Adaptation: The application is wrapped by Falcon::Adapters::Rack. This adapter:
      • Converts the incoming Protocol::HTTP::Request object into a standard Rack env object.
      • Converts the Rack application's output [status, headers, body] into a Falcon::Adapters::Response object (which is derived from Protocol::HTTP::Response).
  3. Falcon server architecture and dependencies

    main

    Falcon acts as a bridge between underlying HTTP protocol objects and the Rack interface. Its architecture relies on the following components:

    • Core Server: Primarily implemented by Async::HTTP::Server.
    • Protocol Implementation: Depends on the protocol-http gems for handling actual protocol logic.
    • Rack Interface: Uses the protocol-rack gem to provide a Rack interface for the HTTP protocol, enabling Falcon to run any Rack-compatible application.
  4. Use Async::Service to manage service lifecycles

    main

    Async::Service provides a generic service layer for managing the lifecycle of various services. Falcon uses this layer to manage its own internal services, such as:

    • Falcon::Service::Server: An HTTP server.
    • Falcon::Service::Supervisor: A process supervisor (e.g., for monitoring memory usage).

    You can use Async::Service to manage any individual service or a group of services.

  5. Falcon's relationship with Async::HTTP and Protocol::Rack

    main

    Falcon acts as a bridge between low-level protocol objects and the Rack interface. It relies on the following components:

    • Server Implementation: Primarily implemented by Async::HTTP::Server, which uses protocol-http gems for protocol implementations.
    • Rack Interface: Uses the protocol-rack gem to provide a Rack interface for the HTTP protocol.

    Note: Falcon is an HTTP server that can run Rack applications; it is not a Rack server itself.

  6. Use WebSockets with Falcon

    main

    Falcon supports WebSockets via the async-websocket gem, enabling bidirectional, real-time communication. To implement WebSockets, use Async::WebSocket::Adapters::Rack.open within a Rack application (e.g., in a config.ru file).

    If the open method successfully establishes a WebSocket connection, it yields a connection object. If it returns nil (meaning the request was not a WebSocket upgrade request), you should return a standard Rack response (e.g., [200, {}, ['Hello World']]) to handle regular HTTP requests.

    # config.ru
    
    require "async/websocket/adapters/rack"
    
    run do |env|
    	Async::WebSocket::Adapters::Rack.open(env, protocols: ['ws']) do |connection|
    		# Simple echo server:
    		while message = connection.read
    			connection.write(message)
    			connection.flush
    		end
    	end or [200, {}, ["Hello World"]]
    end