### Create and Start a Basic HTTP Server with WEBrick Source: https://context7.com/ruby/webrick/llms.txt Initializes an HTTPServer instance with specific port, document root, and logging configurations. The server process is blocking and requires signal traps for graceful shutdown. ```ruby require 'webrick' # Create a basic HTTP server serving static files root = File.expand_path '~/public_html' server = WEBrick::HTTPServer.new( Port: 8000, DocumentRoot: root, Logger: WEBrick::Log.new($stderr, WEBrick::Log::DEBUG), AccessLog: [[$stderr, WEBrick::AccessLog::COMBINED_LOG_FORMAT]] ) # Graceful shutdown on interrupt trap('INT') { server.shutdown } trap('TERM') { server.shutdown } # Start the server (blocking call) server.start ``` -------------------------------- ### Implementing HTTP Basic Authentication with WEBrick Source: https://context7.com/ruby/webrick/llms.txt Set up HTTP Basic Authentication using WEBrick's HTTPAuth module. This example shows how to create or load an htpasswd file and set usernames and passwords with bcrypt hashing for secure storage. ```ruby require 'webrick' require 'webrick/httpauth' # Create or load password file htpasswd = WEBrick::HTTPAuth::Htpasswd.new('/path/to/htpasswd', password_hash: :bcrypt) htpasswd.set_passwd('SecureArea', 'admin', 'secret123') htpasswd.set_passwd('SecureArea', 'user', 'password456') htpasswd.flush ``` -------------------------------- ### Initialize CGI Script Source: https://context7.com/ruby/webrick/llms.txt Start a CGI script using the WEBrick::CGI module for deployment in external web server environments. ```ruby #!/usr/bin/env ruby ``` -------------------------------- ### Install WEBrick via Gemfile Source: https://github.com/ruby/webrick/blob/master/README.md Add the gem dependency to your project's Gemfile. ```ruby gem 'webrick' ``` -------------------------------- ### Start and Shutdown WEBrick Server Source: https://github.com/ruby/webrick/blob/master/README.md Register a signal trap for graceful shutdown and start the server process. ```ruby trap 'INT' do server.shutdown end server.start ``` -------------------------------- ### Initialize WEBrick HTTPServer Source: https://github.com/ruby/webrick/blob/master/README.md Configure a new server instance to listen on a specific port and serve files from a designated directory. ```ruby require 'webrick' root = File.expand_path '~/public_html' server = WEBrick::HTTPServer.new :Port => 8000, :DocumentRoot => root ``` -------------------------------- ### Create HTTPProxyServer Source: https://context7.com/ruby/webrick/llms.txt Demonstrates proxying with content modification, authentication, and upstream proxy routing. ```ruby require 'webrick' require 'webrick/httpproxy' # Basic proxy server proxy = WEBrick::HTTPProxyServer.new( Port: 8080, Logger: WEBrick::Log.new($stderr, WEBrick::Log::DEBUG) ) # Proxy with content modification content_handler = proc do |req, res| # Modify response content if res['content-type']&.include?('text/html') res.body = res.body.to_s.gsub('', '') end # Log proxied requests puts "Proxied: #{req.request_method} #{req.unparsed_uri} -> #{res.status}" end proxy = WEBrick::HTTPProxyServer.new( Port: 8080, ProxyContentHandler: content_handler, ProxyVia: true # Add Via header ) # Proxy with authentication auth_handler = proc do |req, res| WEBrick::HTTPAuth.proxy_basic_auth(req, res, 'ProxyRealm') do |user, pass| user == 'proxyuser' && pass == 'proxypass' end end proxy = WEBrick::HTTPProxyServer.new( Port: 8080, ProxyAuthProc: auth_handler ) # Proxy through upstream proxy proxy = WEBrick::HTTPProxyServer.new( Port: 8080, ProxyURI: URI.parse('http://upstream-proxy:3128'), ProxyTimeout: true ) trap('INT') { proxy.shutdown } trap('TERM') { proxy.shutdown } proxy.start ``` -------------------------------- ### Utilize WEBrick Utility Functions Source: https://context7.com/ruby/webrick/llms.txt Demonstrates common utility tasks including timeout management, socket creation, and privilege handling. ```ruby require 'webrick' # Timeout handling begin WEBrick::Utils.timeout(5, Timeout::Error) do # Operation that might take too long sleep 3 puts "Completed within timeout" end rescue Timeout::Error puts "Operation timed out!" end # Create TCP listeners listeners = WEBrick::Utils.create_listeners('0.0.0.0', 8000) puts "Created #{listeners.size} listener(s)" listeners.each(&:close) # Generate random strings (useful for tokens, session IDs) token = WEBrick::Utils.random_string(32) puts "Random token: #{token}" # Get server hostname hostname = WEBrick::Utils.getservername puts "Server hostname: #{hostname}" # Switch user (requires root) # WEBrick::Utils.su('nobody') # Set socket options socket = TCPSocket.new('localhost', 80) rescue nil if socket WEBrick::Utils.set_non_blocking(socket) WEBrick::Utils.set_close_on_exec(socket) socket.close end # TimeoutHandler for custom timeout management handler_id = WEBrick::Utils::TimeoutHandler.register(10, RuntimeError) begin # Long running operation sleep 5 ensure WEBrick::Utils::TimeoutHandler.cancel(handler_id) end ``` -------------------------------- ### Building HTTP Responses with WEBrick Source: https://context7.com/ruby/webrick/llms.txt Demonstrates how to construct various HTTP responses using WEBrick, including setting status codes, headers, plain text and JSON bodies, cookies, file downloads, and chunked streaming. Also shows how to send error responses. ```ruby require 'webrick' require 'json' server = WEBrick::HTTPServer.new(Port: 8000) # Basic response with headers server.mount_proc '/hello' do |req, res| res.status = 200 res['Content-Type'] = 'text/plain' res['X-Custom-Header'] = 'CustomValue' res['Cache-Control'] = 'no-cache' res.body = 'Hello, World!' end # JSON response server.mount_proc '/json' do |req, res| res.status = 200 res['Content-Type'] = 'application/json' res.body = JSON.generate({ status: 'ok', timestamp: Time.now.iso8601 }) end # Setting cookies server.mount_proc '/set-cookie' do |req, res| cookie = WEBrick::Cookie.new('session_id', 'abc123') cookie.path = '/' cookie.max_age = 3600 # 1 hour cookie.secure = false res.cookies << cookie res['Content-Type'] = 'text/plain' res.body = 'Cookie set!' end # File download response server.mount_proc '/download' do |req, res| file_path = '/path/to/file.pdf' res['Content-Type'] = 'application/pdf' res['Content-Disposition'] = 'attachment; filename="document.pdf"' res.body = File.open(file_path, 'rb') end # Chunked streaming response server.mount_proc '/stream' do |req, res| res.chunked = true res['Content-Type'] = 'text/plain' res.body = proc do |out| 5.times do |i| out.write("Chunk #{i + 1}\n") sleep 1 end end end # Error responses server.mount_proc '/error' do |req, res| res.status = 500 res['Content-Type'] = 'application/json' res.body = JSON.generate({ error: 'Internal Server Error', code: 500 }) end trap('INT') { server.shutdown } server.start ``` -------------------------------- ### Implement Basic Authentication in WEBrick Source: https://context7.com/ruby/webrick/llms.txt Demonstrates both file-based and inline Basic Authentication for protecting server endpoints. ```ruby # Create authenticator authenticator = WEBrick::HTTPAuth::BasicAuth.new( Realm: 'SecureArea', UserDB: htpasswd ) server = WEBrick::HTTPServer.new(Port: 8000) # Protected endpoint server.mount_proc '/admin' do |req, res| authenticator.authenticate(req, res) res['Content-Type'] = 'text/html' res.body = "

Welcome, #{req.user}!

You have access to the admin area.

" end # Simple inline authentication (without password file) server.mount_proc '/simple-auth' do |req, res| WEBrick::HTTPAuth.basic_auth(req, res, 'Simple Realm') do |user, pass| user == 'demo' && pass == 'demo123' end res['Content-Type'] = 'text/plain' res.body = "Authenticated as: #{req.user}" end trap('INT') { server.shutdown } server.start ``` -------------------------------- ### Configure WEBrick Virtual Hosts Source: https://context7.com/ruby/webrick/llms.txt Define a primary server and attach multiple virtual hosts using the virtual_host method. Set DoNotListen to true for virtual hosts to prevent them from creating separate network listeners. ```ruby # Main server server = WEBrick::HTTPServer.new( Port: 80, ServerName: 'default.example.com', DocumentRoot: '/var/www/default' ) # Virtual host for www.example.com www_host = WEBrick::HTTPServer.new( ServerName: 'www.example.com', DoNotListen: true, # Don't create new listeners DocumentRoot: '/var/www/www' ) www_host.mount_proc '/' do |req, res| res['Content-Type'] = 'text/html' res.body = '

Welcome to www.example.com

' end server.virtual_host(www_host) # Virtual host for api.example.com api_host = WEBrick::HTTPServer.new( ServerName: 'api.example.com', ServerAlias: ['api2.example.com'], # Alternative names DoNotListen: true, DocumentRoot: '/var/www/api' ) api_host.mount_proc '/' do |req, res| res['Content-Type'] = 'application/json' res.body = '{"service": "api.example.com", "status": "ok"}' end server.virtual_host(api_host) # Virtual host with SSL (requires HTTPS setup on main server) # secure_host = WEBrick::HTTPServer.new( # ServerName: 'secure.example.com', # DoNotListen: true, # SSLEnable: true, # SSLCertName: [['CN', 'secure.example.com']] # ) # server.virtual_host(secure_host) trap('INT') { server.shutdown } server.start ``` -------------------------------- ### Serving Static Files and Directories with WEBrick FileHandler Source: https://context7.com/ruby/webrick/llms.txt Configure WEBrick's FileHandler to serve static files and directories. This includes options for fancy indexing, specifying non-disclosure names, and mapping file extensions to handlers. It also shows how to set a custom document root with various options. ```ruby require 'webrick' server = WEBrick::HTTPServer.new(Port: 8000) # Serve static files from a directory with fancy indexing server.mount '/files', WEBrick::HTTPServlet::FileHandler, '/var/www/files', FancyIndexing: true, NondisclosureName: ['.ht*', '*~', '*.bak'], HandlerTable: { 'erb' => WEBrick::HTTPServlet::ERBHandler } # Serve a single file server.mount '/readme', WEBrick::HTTPServlet::DefaultFileHandler, '/var/www/README.txt' # Custom document root with options server = WEBrick::HTTPServer.new( Port: 8000, DocumentRoot: '/var/www/public', DocumentRootOptions: { FancyIndexing: true, DirectoryIndex: ['index.html', 'index.htm', 'default.html'], AcceptableLanguages: ['en', 'ja'] }, MimeTypes: WEBrick::HTTPUtils::DefaultMimeTypes.merge({ 'webp' => 'image/webp', 'woff2' => 'font/woff2' }) ) trap('INT') { server.shutdown } server.start ``` -------------------------------- ### Create Custom Servlets with AbstractServlet Source: https://context7.com/ruby/webrick/llms.txt Implements custom request handling logic by extending AbstractServlet and defining HTTP method handlers like do_GET, do_POST, and do_DELETE. This provides a modular structure for complex applications. ```ruby require 'webrick' require 'json' class ApiServlet < WEBrick::HTTPServlet::AbstractServlet def initialize(server, database) super(server) @database = database end def do_GET(req, res) res['Content-Type'] = 'application/json' res.status = 200 # Extract path info for routing id = req.path_info.split('/').last if id && !id.empty? item = @database[id.to_i] if item res.body = JSON.generate(item) else res.status = 404 res.body = JSON.generate({ error: 'Not found' }) end else res.body = JSON.generate(@database.values) end end def do_POST(req, res) res['Content-Type'] = 'application/json' begin data = JSON.parse(req.body) id = @database.keys.max.to_i + 1 @database[id] = data.merge('id' => id) res.status = 201 res.body = JSON.generate(@database[id]) rescue JSON::ParserError res.status = 400 res.body = JSON.generate({ error: 'Invalid JSON' }) end end def do_DELETE(req, res) id = req.path_info.split('/').last.to_i if @database.delete(id) res.status = 204 else res.status = 404 res['Content-Type'] = 'application/json' res.body = JSON.generate({ error: 'Not found' }) end end end # Usage database = { 1 => { 'id' => 1, 'name' => 'Item 1' } } server = WEBrick::HTTPServer.new(Port: 8000) server.mount '/api/items', ApiServlet, database trap('INT') { server.shutdown } server.start ``` -------------------------------- ### Configure WEBrick Access Logging Source: https://context7.com/ruby/webrick/llms.txt Implement multiple log formats by passing an array of log targets and format constants to the AccessLog option. Use the HUP signal to trigger log file rotation. ```ruby require 'webrick' # Multiple access logs with different formats log_file = File.open('/var/log/webrick/access.log', 'a+') error_log = File.open('/var/log/webrick/error.log', 'a+') server = WEBrick::HTTPServer.new( Port: 8000, Logger: WEBrick::Log.new(error_log, WEBrick::Log::DEBUG), AccessLog: [ # Common Log Format [log_file, WEBrick::AccessLog::COMMON_LOG_FORMAT], # Combined Log Format (includes Referer and User-Agent) [log_file, WEBrick::AccessLog::COMBINED_LOG_FORMAT], # Referer only [$stderr, WEBrick::AccessLog::REFERER_LOG_FORMAT], # Custom format [$stderr, '%h %m %U %s %b %T'] ] ) # Log format placeholders: # %a - Remote IP address # %b - Response size in bytes # %h - Remote host name # %m - Request method # %p - Server port # %q - Query string # %r - First line of request # %s - Status code # %t - Time of request (CLF format) # %T - Time taken to process request # %u - Authenticated user # %U - URL path # %{Header}i - Request header value # %{Header}o - Response header value # Log rotation on HUP signal trap('HUP') { log_file.reopen('/var/log/webrick/access.log', 'a+') } server.mount_proc '/' do |req, res| res.body = 'Hello!' end trap('INT') { server.shutdown } server.start ``` -------------------------------- ### Configure HTTPS SSL/TLS Server Source: https://context7.com/ruby/webrick/llms.txt Provides options for auto-generated self-signed certificates, custom certificate files, and full SSL/TLS configuration. ```ruby require 'webrick' require 'webrick/https' # Option 1: Auto-generated self-signed certificate server = WEBrick::HTTPServer.new( Port: 8443, SSLEnable: true, SSLCertName: [['CN', 'localhost']] ) # Option 2: Custom certificate and key require 'openssl' cert = OpenSSL::X509::Certificate.new(File.read('/path/to/cert.pem')) key = OpenSSL::PKey::RSA.new(File.read('/path/to/key.pem')) server = WEBrick::HTTPServer.new( Port: 8443, SSLEnable: true, SSLCertificate: cert, SSLPrivateKey: key, SSLVerifyClient: OpenSSL::SSL::VERIFY_NONE ) # Option 3: Full SSL configuration server = WEBrick::HTTPServer.new( Port: 8443, SSLEnable: true, SSLCertificate: cert, SSLPrivateKey: key, SSLCACertificateFile: '/path/to/ca-bundle.crt', SSLVerifyClient: OpenSSL::SSL::VERIFY_PEER, SSLVerifyDepth: 3, SSLCiphers: 'HIGH:!aNULL:!MD5', SSLTimeout: 30 ) server.mount_proc '/' do |req, res| res['Content-Type'] = 'text/html' res.body = '

Secure Connection!

' res.body += "

SSL Cipher: #{req.cipher[0]}

" if req.cipher end trap('INT') { server.shutdown } server.start ``` -------------------------------- ### Implement a WEBrick CGI Application Source: https://context7.com/ruby/webrick/llms.txt Defines a CGI handler by inheriting from WEBrick::CGI and implementing do_GET and do_POST methods. ```ruby require 'webrick/cgi' class MyCGI < WEBrick::CGI def do_GET(req, res) res['Content-Type'] = 'text/html' res.status = 200 res.body = <<-HTML

WEBrick CGI Application

Request Path: #{req.path_info}

Query String: #{req.query_string}

Remote Address: #{req.peeraddr[3]}

Server: #{req.server_name}:#{req.port}

HTML end def do_POST(req, res) res['Content-Type'] = 'application/json' res.status = 200 # Access form data data = {} req.query.each { |k, v| data[k] = v } res.body = JSON.generate({ method: 'POST', data: data, content_type: req.content_type }) end end # Start CGI handler MyCGI.new.start ``` -------------------------------- ### Daemonize a WEBrick Server Source: https://context7.com/ruby/webrick/llms.txt Configures a server to run as a background process with privilege dropping capabilities. ```ruby require 'webrick' # Simple daemon mode if ARGV.include?('--daemon') WEBrick::Daemon.start end server = WEBrick::HTTPServer.new( Port: 8000, Logger: WEBrick::Log.new('/var/log/webrick.log'), ServerType: ARGV.include?('--daemon') ? WEBrick::Daemon : WEBrick::SimpleServer ) # Privilege dropping for binding to port 80 # Run as root to bind, then drop to www user if Process.uid == 0 # Create listeners as root sockets = WEBrick::Utils.create_listeners(nil, 80) # Drop privileges WEBrick::Utils.su('www-data') # Create server that doesn't listen server = WEBrick::HTTPServer.new( DoNotListen: true, Logger: WEBrick::Log.new('/var/log/webrick.log') ) # Replace listeners with privileged sockets server.listeners.replace(sockets) end server.mount_proc '/' do |req, res| res.body = 'Running as daemon!' end # PID file management pid_file = '/var/run/webrick.pid' File.write(pid_file, Process.pid.to_s) at_exit { File.delete(pid_file) if File.exist?(pid_file) } trap('INT') { server.shutdown } trap('TERM') { server.shutdown } server.start ``` -------------------------------- ### Handle HTTP Requests with Ruby Blocks using mount_proc Source: https://context7.com/ruby/webrick/llms.txt Uses mount_proc to define request handlers for specific paths, providing access to request and response objects. This approach is suitable for simple routing, JSON APIs, and redirects. ```ruby require 'webrick' require 'json' server = WEBrick::HTTPServer.new(Port: 8000) # Simple text response server.mount_proc '/' do |req, res| res['Content-Type'] = 'text/html' res.body = '

Welcome to WEBrick!

' end # JSON API endpoint with query parameters server.mount_proc '/api/users' do |req, res| res['Content-Type'] = 'application/json' case req.request_method when 'GET' # Access query parameters name = req.query['name'] || 'Guest' res.body = JSON.generate({ message: "Hello, #{name}!", method: 'GET' }) when 'POST' # Access POST body data = JSON.parse(req.body) rescue {} res.body = JSON.generate({ received: data, status: 'created' }) res.status = 201 else res.status = 405 res.body = JSON.generate({ error: 'Method not allowed' }) end end # Redirect example server.mount_proc '/old-path' do |req, res| res.set_redirect(WEBrick::HTTPStatus::MovedPermanently, '/new-path') end trap('INT') { server.shutdown } server.start ``` -------------------------------- ### Accessing HTTP Request Information in WEBrick Source: https://context7.com/ruby/webrick/llms.txt Use this snippet to access and log various details of an incoming HTTP request, including method, URI, headers, query parameters, and client information. It handles POST/PUT requests by logging the request body. ```ruby require 'webrick' server = WEBrick::HTTPServer.new(Port: 8000) server.mount_proc '/debug' do |req, res| res['Content-Type'] = 'text/plain' info = [] info << "Request Method: #{req.request_method}" info << "Request URI: #{req.request_uri}" info << "Path: #{req.path}" info << "Path Info: #{req.path_info}" info << "Script Name: #{req.script_name}" info << "Query String: #{req.query_string}" info << "HTTP Version: #{req.http_version}" info << "" info << "Query Parameters:" req.query.each { |k, v| info << " #{k} = #{v}" } info << "" info << "Headers:" req.each { |name, value| info << " #{name}: #{value}" } info << "" info << "Cookies:" req.cookies.each { |cookie| info << " #{cookie.name} = #{cookie.value}" } info << "" info << "Client Info:" info << " Remote IP: #{req.peeraddr[3]}" info << " Host: #{req.host}" info << " Port: #{req.port}" info << " Keep-Alive: #{req.keep_alive?}" info << "" info << "Content-Type: #{req.content_type}" info << "Content-Length: #{req['content-length']}" # Access request body for POST/PUT if %w[POST PUT].include?(req.request_method) info << "" info << "Body:" info << req.body.to_s end res.body = info.join("\n") end trap('INT') { server.shutdown } server.start ``` -------------------------------- ### Implement Digest Authentication Source: https://context7.com/ruby/webrick/llms.txt Uses MD5/SHA1 digest computation to secure credentials. The authenticator instance must be reused across requests. ```ruby require 'webrick' require 'webrick/httpauth' # Create digest password file htdigest = WEBrick::HTTPAuth::Htdigest.new('/path/to/htdigest') htdigest.set_passwd('DigestRealm', 'admin', 'secret123') htdigest.flush # Create digest authenticator (must be reused across requests) digest_auth = WEBrick::HTTPAuth::DigestAuth.new( Realm: 'DigestRealm', UserDB: htdigest, Algorithm: 'MD5', Qop: ['auth'] # Quality of protection ) # Custom servlet with digest authentication class SecureApiServlet < WEBrick::HTTPServlet::AbstractServlet def initialize(server, authenticator) super(server) @authenticator = authenticator end def do_GET(req, res) @authenticator.authenticate(req, res) res['Content-Type'] = 'application/json' res.body = JSON.generate({ message: 'Secure data', user: req.user, authenticated_at: Time.now.iso8601 }) end end server = WEBrick::HTTPServer.new(Port: 8000) server.mount '/secure', SecureApiServlet, digest_auth trap('INT') { server.shutdown } server.start ``` -------------------------------- ### Manage HTTP Cookies in WEBrick Source: https://context7.com/ruby/webrick/llms.txt Use the WEBrick::Cookie class to read incoming cookies from requests and append new cookies to the response. The parse_set_cookie method is available for parsing raw Set-Cookie header strings. ```ruby require 'webrick' server = WEBrick::HTTPServer.new(Port: 8000) server.mount_proc '/cookies' do |req, res| res['Content-Type'] = 'text/html' # Read existing cookies cookies_html = "

Received Cookies:

" # Set a simple session cookie session_cookie = WEBrick::Cookie.new('session', 'xyz789') session_cookie.path = '/' res.cookies << session_cookie # Set a persistent cookie with expiration persistent = WEBrick::Cookie.new('remember', 'true') persistent.path = '/' persistent.max_age = 30 * 24 * 60 * 60 # 30 days persistent.secure = false persistent.domain = 'localhost' res.cookies << persistent # Set a cookie with expiration date expiring = WEBrick::Cookie.new('expires_demo', 'value') expiring.expires = Time.now + 3600 # 1 hour from now expiring.path = '/' res.cookies << expiring res.body = <<-HTML

Cookie Demo

#{cookies_html}

Set Cookies:

Refresh to see cookies

HTML end # Parse Set-Cookie headers (useful for proxies or clients) server.mount_proc '/parse-cookie' do |req, res| set_cookie_header = 'session=abc123; Path=/; Max-Age=3600; Secure; HttpOnly' parsed = WEBrick::Cookie.parse_set_cookie(set_cookie_header) res['Content-Type'] = 'application/json' res.body = JSON.generate({ name: parsed.name, value: parsed.value, path: parsed.path, max_age: parsed.max_age, secure: parsed.secure }) end trap('INT') { server.shutdown } server.start ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.