WEBrick HTTP Server Toolkit

repository·master·Indexed 43 days ago

https://github.com/ruby/webrick

An HTTP server toolkit for Ruby designed for testing and local development. It provides a flexible framework for creating HTTP/HTTPS servers, proxy servers, and virtual-host servers with built-in support for logging, authentication (Basic and Digest), and various servlets. Key components include WEBrick::HTTPServer, WEBrick::HTTPProxyServer, and WEBrick::HTTPAuth::Htpasswd for managing Apache-compatible password files.

Tokens
10.6K
Snippets
46
Records
60
Agent score
55%

What's inside WEBrick

  1. What is WEBrick and when should I use it?

    master

    WEBrick is an HTTP server toolkit that supports HTTPS, proxying, and virtual-host configurations. It features complete logging for server operations and HTTP access, and supports basic and digest authentication.

    Important Usage Note: WEBrick is intended for testing and local development only. It is not intended for production use and should not receive traffic from untrusted sources.

  2. Install WEBrick

    master

    You can install WEBrick using Bundler by adding it to your Gemfile, or by installing the gem directly via the command line.

    Using Bundler: Add gem 'webrick' to your Gemfile and run bundle.

    Direct Installation: Run gem install webrick.

    gem 'webrick'
  3. Implement a custom HTTP authentication scheme

    master

    To create a custom authentication mechanism in WEBrick, you must include the WEBrick::HTTPAuth::Authenticator module in your class. Your implementation must override the AuthScheme constant to specify the authentication type (e.g., 'Basic' or 'Digest').

    When initializing your authenticator via check_init(config), the following configuration keys are required:

    • :Realm: The realm name this authenticator covers.
    • :UserDB: The user database used for credential verification.

    Optional configuration keys:

    • :Logger: A logger instance (defaults to Log.new($stderr) if not provided).
    • :AutoReloadUserDB: A flag to enable automatic reloading of the user database.
    module MyCustomAuth
      include WEBrick::HTTPAuth::Authenticator
    
      AuthScheme = 'CustomScheme'
      RequestField = 'Authorization'
      ResponseField = 'WWW-Authenticate'
      ResponseInfoField = 'Authentication-Info'
      AuthException = WEBrick::HTTPStatus::Unauthorized
    
      # You must implement the actual logic for verifying credentials
      # using the methods provided by the Authenticator module.
    end
  4. Handle HTTP status codes and exceptions in WEBrick

    master

    WEBrick provides a hierarchy of exception classes under WEBrick::HTTPStatus::Status to represent HTTP status codes. These classes can be raised to signal specific HTTP responses. The hierarchy is organized by status type:

    • WEBrick::HTTPStatus::Info (1xx)
    • WEBrick::HTTPStatus::Success (2xx)
    • WEBrick::HTTPStatus::Redirect (3xx)
    • WEBrick::HTTPStatus::Error (4xx/5xx)
      • WEBrick::HTTPStatus::ClientError (4xx)
      • WEBrick::HTTPStatus::ServerError (5xx)

    Each status class instance provides access to its numeric code and its reason_phrase (e.g., "Not Found").

    begin
      # Example of raising a specific status error
      raise WEBrick::HTTPStatus::NotFound
    rescue WEBrick::HTTPStatus::Status => e
      puts "Error Code: #{e.code}"
      puts "Reason: #{e.reason_phrase}"
    end
  5. Reuse servlet instances with get_instance

    master

    By default, AbstractServlet creates a new instance for every incoming request. If you want to reuse a single servlet instance across multiple requests (for example, to maintain state or reduce overhead), override the class method self.get_instance(server, *options) in your subclass.

    class SingletonServlet < WEBrick::HTTPServlet::AbstractServlet
      # This ensures the same instance is used for all requests
      def self.get_instance(server, *options)
        @instance ||= new(server, *options)
      end
    end
  6. Configure Virtual Hosts

    master

    A WEBrick server can act as a virtual host for multiple hostnames. You can create additional WEBrick::HTTPServer instances that do not listen on a network socket by setting :DoNotListen => true. These virtual hosts can then be attached to a primary listening server using server.virtual_host vhost.

    server = WEBrick::HTTPServer.new
    
    vhost = WEBrick::HTTPServer.new(
      :ServerName => 'vhost.example',
      :DoNotListen => true
    )
    
    vhost.mount '/', SomeServlet
    
    server.virtual_host vhost
  7. Manage Apache-compatible password files with Htpasswd

    master

    The WEBrick::HTTPAuth::Htpasswd class provides a way to manage Apache-compatible .htpasswd files. It is designed to be used with WEBrick::HTTPAuth::BasicAuth to handle user authentication. For security, ensure the password database file is stored outside of the paths accessible to the HTTP server.

    Supported Password Hashes

    You can specify the hashing algorithm during initialization using the password_hash keyword argument:

    • :crypt: The default algorithm. Requires string/crypt to be available (otherwise it falls back to the deprecated String#crypt).
    • :bcrypt: Uses the bcrypt gem. This is recommended for modern security requirements.

    Note: If you initialize with :bcrypt, the file must not contain legacy crypt passwords. Conversely, if you use :crypt, the file must not contain bcrypt passwords.

    htpasswd = WEBrick::HTTPAuth::Htpasswd.new 'my_password_file', password_hash: :bcrypt
    htpasswd.set_passwd 'my realm', 'username', 'password'
    htpasswd.flush
  8. Implement a custom server by subclassing GenericServer

    master

    To create a custom TCP server, you must subclass WEBrick::GenericServer and implement the run(sock) method. The run method is called within a new thread for every accepted client connection and must accept a single sock argument representing the client socket.

    If you provide a block to start, the block will be executed instead of run.

    class MyServer < WEBrick::GenericServer
      def run(sock)
        # Handle the client socket here
        puts "Received connection from #{sock.peeraddr}"
        sock.write("Hello from custom server\n")
      end
    end
    
    server = MyServer.new(Port: 8080)
    server.start
  9. Configure custom servlets with arguments

    master

    Servlets can be initialized with custom arguments. When overriding initialize, ensure you call super server where server is the first argument. These arguments are stored in the @options instance variable.

    To pass these arguments during mounting, provide them as additional arguments to the server.mount method.

    class Configurable < WEBrick::HTTPServlet::AbstractServlet
      def initialize(server, color, size)
        super(server)
        @color = color
        @size = size
      end
    
      def do_GET(request, response)
        content = "<p style=\"color: #{@color}; font-size: #{@size}\">Hello, World!</</p>"
        response.status = 200
        response['Content-Type'] = 'text/html'
        response.body = content
      end
    end
    
    # Pass 'red' and '2em' as configuration arguments at mount time
    server.mount '/configurable', Configurable, 'red', '2em'
  10. Create a simple HTTP Proxy server

    master

    To create a basic HTTP proxy server using WEBrick, require webrick and webrick/httpproxy, then instantiate WEBrick::HTTPProxyServer with a Port option. You should also implement signal traps (like INT or TERM) to ensure the server shuts down gracefully.

    require 'webrick'
    require 'webrick/httpproxy'
    
    proxy = WEBrick::HTTPProxyServer.new Port: 8000
    
    trap 'INT'  do proxy.shutdown end
    trap 'TERM' do proxy.shutdown end
    
    proxy.start
  11. Configure an HTTPS server

    master

    To enable HTTPS, require webrick/https and set :SSLEnable => true.

    Option 1: Self-signed certificate Provide a :SSLCertName array (e.g., [['CN', 'localhost']]). WEBrick will generate a self-signed certificate that changes every time the server restarts.

    Option 2: Pre-determined certificate and key Provide an OpenSSL::X509::Certificate object to :SSLCertificate and an OpenSSL::PKey::RSA object to :SSLPrivateKey.

    require 'webrick'
    require 'webrick/https'
    
    # Using self-signed certificate
    server = WEBrick::HTTPServer.new(
      :Port => 8000,
      :SSLEnable => true,
      :SSLCertName => [['CN', 'localhost']]
    )
    
    # Using existing certificate and key
    require 'openssl'
    cert = OpenSSL::X509::Certificate.new File.read '/path/to/cert.pem'
    pkey = OpenSSL::PKey::RSA.new File.read '/path/to/pkey.pem'
    
    server = WEBrick::HTTPServer.new(
      :Port => 8000,
      :SSLEnable => true,
      :SSLCertificate => cert,
      :SSLPrivateKey => pkey
    )
  12. Start a basic HTTP server

    master

    To create a new WEBrick::HTTPServer that listens on a specific port and serves files from a directory, initialize it with :Port and :DocumentRoot options. Note that server.start is a blocking call, so you should implement a shutdown hook (e.g., using trap 'INT') to allow the server to stop gracefully.

    Warning: WEBrick is intended for testing and local development, not for production use or receiving traffic from untrusted sources.

    require 'webrick'
    
    root = File.expand_path '~/public_html'
    server = WEBrick::HTTPServer.new :Port => 8000, :DocumentRoot => root
    
    trap 'INT' do server.shutdown end
    
    server.start