Class: Stipa::App
- Inherits:
-
Object
- Object
- Stipa::App
- Defined in:
- lib/stipa/app.rb
Overview
User-facing DSL for defining routes and middleware.
Usage:
app = Stipa::App.new
app.use Stipa::Middleware::RequestId
app.use Stipa::Middleware::Timing
app.use Stipa::Middleware::Cors, origins: ['https://example.com']
app.get '/' { |_req, res| res.body = 'Hello' }
app.get '/health' { |_req, res| res.json(status: 'ok') }
app.post '/echo' { |req, res| res.body = req.body }
app.get %r{/users/(?<id>\d+)} { |req, res| res.json(id: req.params[:id].to_i) }
app.start(port: 3710)
Handler signature:
Handlers always receive (req, res) — both the Request and the Response.
Mutate `res` directly: res.body = ..., res.status = ..., res.json(...).
Return value of the block is ignored; mutating `res` is the contract.
Route matching:
- String patterns: exact path match only.
- Regexp patterns: full match via Regexp#match. Named capture groups
(e.g., (?<id>\d+)) are placed into req.params as symbol keys.
- Routes are checked in insertion order; first match wins.
Middleware:
- call `use` before `start`. Order matters: first `use`-d runs first.
- The chain is compiled once at start time; calling `use` afterwards
has no effect (a warning is logged).
Constant Summary collapse
- HTTP_VERBS =
%w[get post put patch delete head options].freeze
Instance Method Summary collapse
-
#initialize(views: nil, public: nil) ⇒ App
constructor
views: path to the views directory (enables ERB rendering via res.render) public: path to the public directory (enables static file serving) When provided, Static middleware is automatically prepended.
-
#start(**opts) ⇒ Object
Build the middleware chain and start the TCP server.
-
#use(middleware, **opts) ⇒ Object
Add a middleware to the stack.
Constructor Details
#initialize(views: nil, public: nil) ⇒ App
views: path to the views directory (enables ERB rendering via res.render) public: path to the public directory (enables static file serving)
When provided, Static middleware is automatically prepended.
47 48 49 50 51 52 53 54 |
# File 'lib/stipa/app.rb', line 47 def initialize(views: nil, public: nil) @routes = [] @stack = MiddlewareStack.new @started = false @logger = Logger.new @template_engine = views ? Template.new(views_dir: views) : nil @public_dir = public ? File.(public) : nil end |
Instance Method Details
#start(**opts) ⇒ Object
Build the middleware chain and start the TCP server. Blocks until shutdown.
75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/stipa/app.rb', line 75 def start(**opts) @started = true # Prepend Static middleware automatically when a public dir is configured. # It runs before all user-registered middleware so static assets are served # without going through the full middleware stack. if @public_dir @stack.prepend(Middleware::Static, root: @public_dir) end chain = @stack.build(method(:dispatch)) Server.new(app: chain, **opts).start end |
#use(middleware, **opts) ⇒ Object
Add a middleware to the stack. Must be called before start.
65 66 67 68 69 70 71 72 |
# File 'lib/stipa/app.rb', line 65 def use(middleware, **opts) if @started @logger.warn("use() called after start — #{middleware} will be ignored") return self end @stack.use(middleware, **opts) self end |