Plug.Cowboy

repository·master·Indexed 42 days ago

https://github.com/elixir-plug/plug_cowboy

A Plug adapter for the Cowboy web server that allows developers to run Plug-based applications on top of the Cowboy engine. It provides utilities for sending responses via send_resp/4, serving files with send_file/6, handling chunked responses, reading request bodies, and upgrading connections to WebSockets.

Tokens
1.3K
Snippets
9
Records
10
Agent score
4%

What's inside Plug.Cowboy

  1. Run Plug.Cowboy as a supervised handler

    master

    To ensure reliability, start Plug.Cowboy as a child process within an OTP supervision tree. In your application's start/2 function, include the Plug.Cowboy specification in your list of children.

    Common configuration keys for the child specification include:

    • scheme: The protocol to use (e.g., :http).
    • plug: The module implementing your Plug pipeline.
    • port: The port number to listen on.
    defmodule MyApp do
      @moduledoc false
    
      use Application
    
      def start(_type, _args) do
        children = [
          {Plug.Cowboy, scheme: :http, plug: MyApp, port: 4040}
        ]
    
        opts = [strategy: :one_for_one, name: MyApp.Supervisor]
        Supervisor.start_link(children, opts)
      end
    end
  2. Send responses with send_resp/4

    master

    Use send_resp/4 to send a standard HTTP response. It takes the connection (req), an integer status code, a list or map of headers, and the response body. It automatically handles the status reason phrase (e.g., 200 OK).

    # Example usage
    Plug.Cowboy.Conn.send_resp(conn, 200, %{"Content-Type" => "text/plain"}, "Hello, World!")
  3. Upgrade to WebSocket with upgrade/3

    master

    To upgrade an HTTP connection to a WebSocket, use upgrade/3.

    Note: The args parameter must follow a specific format for Cowboy: {handler :: atom(), arg :: term(), opts :: map()}. If the format is incorrect, an ArgumentError is raised.

    # Correct format for WebSocket upgrade
    args = {:my_websocket_handler, %{state: :init}, %{}} 
    Plug.Cowboy.Conn.upgrade(conn, :websocket, args)
  4. Retrieve socket and peer data

    master

    Use these functions to extract low-level connection information:

    • get_sock_data(req): Returns %{address: addr, port: port} representing the underlying socket.
    • get_peer_data(req): Returns %{address: ip, port: port, ssl_cert: cert}. The ssl_cert is nil if no certificate is present.
    • get_http_protocol(req): Returns the HTTP version (e.g., :http1, :http2).
  5. Read request body with read_req_body/2

    master

    Read the body of an incoming request. You can pass an options keyword list to control the reading behavior.

    Supported options:

    • :length: The maximum total number of bytes to read (default: 8_000_000).
    • :read_length: The amount of data to read in each iteration (default: 1_000_000).
    • :read_timeout: The timeout for each read operation in milliseconds (default: 15_000).
    # Read body with custom limits
    {:ok, body, conn} = Plug.Cowboy.Conn.read_req_body(conn, [length: 1_000_000, read_timeout: 5_000])
  6. Send files with send_file/6

    master

    Use send_file/6 to efficiently serve files from the filesystem. This utilizes the :sendfile mechanism in Cowboy.

    Arguments:

    • req: The connection.
    • status: Integer status code.
    • headers: List or map of headers.
    • path: Filesystem path to the file.
    • offset: Starting byte offset.
    • length: Either :all to send the whole file or an integer specifying the number of bytes.
    # Send the entire file
    Plug.Cowboy.Conn.send_file(conn, 200, %{}, "/path/to/file.txt", 0, :all)
  7. Handle chunked responses with send_chunked/3 and chunk/2

    master

    For streaming responses, use send_chunked/3 to initiate a chunked transfer encoding, followed by one or more calls to chunk/2 to send data segments.

    # 1. Start the chunked response
    conn = Plug.Cowboy.Conn.send_chunked(conn, 200, %{"Content-Type" => "text/plain"})
    
    # 2. Send chunks of data
    Plug.Cowboy.Conn.chunk(conn, "First chunk\n")
    Plug.Cowboy.Conn.chunk(conn, "Second chunk\n")