Note that once an on block matches, processing halts at the conclusion of that block.

Status codes

If you don't assign a status code and you don't write to the res
object, the status will be set as 404. The method not_found is
in charge of setting the proper status code, and you can redefine
it if you want to render a template or configure custom headers.

Security

The most important security consideration is to use https for all
requests. If that's not the case, any attempt to secure the application
could be in vain. The rest of this section assumes https is
enforced.

When building a web application, you need to include a security
layer. Cuba ships with the Cuba::Safe plugin, which applies several
security related headers to prevent attacks like clickjacking and
cross-site scripting, among others. It is not included by default
because there are legitimate uses for plain Cuba (for instance,
when designing an API).

HTTP Verbs

There are matchers defined for the following HTTP Verbs: get,
post, put, patch, delete, head, options, link, unlink
and trace. As you have the whole request available via the req
object, you can also query it with helper methods like req.options?
or req.head?, or you can even go to a lower level and inspect the
environment via the env object, and check for example if
env["REQUEST_METHOD"] equals the verb PATCH.

What follows is an example of different ways of saying the same thing:

on env["REQUEST_METHOD"] == "GET", "api" do ... end
on req.get?, "api" do ... end
on get, "api" do ... end

Actually, get is syntax sugar for req.get?, which in turn is syntax sugar
for env["REQUEST_METHOD"] == "GET".

Headers

You can set the headers by assigning values to the hash req.headers.
If you want to inspect the incoming headers, you have to read from
the env hash. For example, if you want to know the referrer you
can check env["HTTP_REFERER"].

Request and Response

You may have noticed we use req and res a lot. Those variables are
instances of Rack::Request and Cuba::Response respectively, and
Cuba::Response is just an optimized version of
Rack::Response.

Those objects are helpers for accessing the request and for building
the response. Most of the time, you will just use res.write.

If you want to use custom Request or Response objects, you can
set the new values as follows:

Embedding routes from other modules

While the run command allows you to handle over the control to a
sub app, sometimes you may want to just embed routes defined in
another module. There's no built-in method to do it, but if you are
willing to experiment you can try the following.

Let's say you have defined routes in modules A and B, and you
want to mount those routes in your application.

It should halt the request only if the resulting status from calling
the mounted app is not 404. If you run into some unexpected behavior,
let me know by creating an issue and we'll look at how to workaround
any difficulties.

Testing

Given that Cuba is essentially Rack, it is very easy to test with
Rack::Test, Webrat or Capybara. Cuba's own tests are written
with a combination of Cutest and Rack::Test,
and if you want to use the same for your tests it is as easy as
requiring cuba/test:

Rendering

Cuba includes a plugin called Cuba::Render that provides a couple of helper
methods for rendering templates. This plugin uses Tilt, which serves as
an interface to a bunch of different Ruby template engines (ERB, Haml, Sass,
CoffeeScript, etc.), so you can use the template engine of your choice.

This example uses ERB, a template engine that comes with Ruby. If you want to
use another template engine, one supported by Tilt, you need to
install the required gem and change the template_engine setting as shown
below.

The plugin provides three helper methods for rendering templates: partial,
view and render.

Cuba.definedoon"about"do# `partial` renders a template called `about.erb` without a layout.
res.writepartial("about")endon"home"do# Opposed to `partial`, `view` renders the same template
# within a layout called `layout.erb`.
res.writeview("about")endon"contact"do# `render` is a shortcut to `res.write view(...)`
render("contact")endend

By default, Cuba::Render assumes that all templates are placed in a folder
named views and that they use the proper extension for the chosen template
engine. Also for the view and render methods, it assumes that the layout
template is called layout.

Contributing

A good first step is to meet us on IRC and discuss ideas. If that's
not possible, you can create an issue explaning the proposed change
and a use case. We pay a lot of attention to use cases, because our
goal is to keep the code base simple. In many cases, the result of
a conversation will be the creation of another tool, instead of the
modification of Cuba itself.

If you want to test Cuba, you may want to use a gemset to isolate
the requirements. We recommend the use of tools like dep and
gs, but you can use similar tools like gst or bs.

The required gems for testing and development are listed in the
.gems file. If you are using dep, you can create a gemset
and run dep install.