Otto - 1.2 (2025-08-18)

Define your rack-apps in plain-text with built-in security.

Otto mascot

Otto apps have three files: a rackup file, a Ruby class, and a routes file. The routes file is just plain text that maps URLs to Ruby methods.

$ cd myapp && ls
config.ru app.rb routes

Routes File

# routes

GET   /                         App#index
POST  /feedback                 App#receive_feedback
GET   /product/:id              App#show_product
GET   /robots.txt               App#robots_text
GET   /404                      App#not_found

Ruby Class

# app.rb

class App
  def initialize(req, res)
    @req, @res = req, res
  end

  def index
    res.body = '<h1>Hello Otto</h1>'
  end

  def show_product
    product_id = req.params[:id]
    res.body = "Product: #{product_id}"
  end

  def robots_text
    res.header['Content-Type'] = "text/plain"
    rules = 'User-agent: *', 'Disallow: /private/keep/out'
    res.body = rules.join($/)
  end
end

Rackup File

# config.ru

require 'otto'
require 'app'

run Otto.new("./routes")

Security Features

Otto includes optional security features for production apps:

# Enable security features
app = Otto.new("./routes", {
  csrf_protection: true,      # CSRF tokens and validation
  request_validation: true,   # Input sanitization and limits
  trusted_proxies: ['10.0.0.0/8']
})

Security features include CSRF protection, input validation, security headers, and trusted proxy configuration.

Requirements

  • Ruby 3.4+
  • Rack 3.1+

Installation

gem install otto

AI Development Assistance

Version 1.2.0's security features were developed with AI assistance:

  • Zed Agent (Claude Sonnet 4) - Security implementation and testing
  • Claude Desktop - Rack 3+ compatibility and debugging
  • GitHub Copilot - Code completion

The maintainer remains responsible for all security decisions and implementation. We believe in transparency about development tools, especially for security-focused software.

License

See LICENSE.txt