README.md

Urna - REST in peace
====================
*Urna* is a simple DSL around [cauldron](https://github.com/meh/cauldron) to
implement REST services.

Basics
------
*Urna* tries to follow the REST style as closely as possible, there are
namespaces and resources, and standard requests to these resources will receive
proper answers.

It includes `OPTIONS` requests being properly processed, requests on non-existent
resources being answered with `404` and verbs not implemented for the resource being
answered with a `405`.

```elixir
defmodule Example do
  use Urna

  # namespace is used to define an additional path to access the resource, in
  # this case /foo/.
  namespace :foo do
    # resource is used to, you guessed it, define a resource, since we're in
    # the :foo namespace it will be accessible at /foo/bar.
    resource :bar do
      # A get without a parameter responds to a GET request to the resource, in
      # this case /foo/bar.
      #
      # The result of the block is automatically converted to an accepted
      # content type extracted from the Accept header.
      get do
        42
      end

      # A get with a parameter responds to a GET request to the resource with
      # an additional value, in this case /foo/bar/:id.
      get id do
        id
      end

      # A post without a parameter, alike get, responds to a POST request to
      # the resource, again in this case /foo/bar.
      #
      # You can access the decoded content in the params variable, the decoding
      # is done based on the Content-Type header assumed there's an available
      # decoder for that type.
      post do
        params["id"]
      end

      # Other common verbs are available: head, get, post, put, delete.
      #
      # If you want you can define your own verbs too, instead of using the
      # available ones you can use the verb function.
      #
      # In this case it will respond to a HUE request on /foo/bar.
      verb "HUE" do
        "huehuehuehue"
      end
    end
  end
end
```

Replying to or failing the request
----------------------------------
Sometimes you want to answer with a failure or a success with a specific
response code and text.

To do this you can use the `reply` and `fail` functions. Both functions take as
first parameter the error code, unless a text parameter is given it will use
the standard text.

If a result is also given, it's expected as first parameter.

```elixir
defmodule Example do
  use Urna

  resource :foo do
    # I'm a tea pot.
    get do
      fail 418
    end
  end

  resource :bar do
    # Here you could do something with the parameters and write a row to a
    # table, so you'd want to answer to the request with a 201 (Created)
    # response, on top with the newly created row.
    post do
      Hey.create(params) |> reply 201
    end
  end
end
```

Verb parameter conversion
-------------------------
*Urna* also supports converting the verb parameter to an `integer` or `float`,
for more complex conversion you'll have to deal it yourself.

```elixir
defmodule Example do
  use Urna

  resource :baz do
    get id, as: Integer do

    end
  end
end
```

Accessing various variables
---------------------------
On top of `params` there are other useful variables you can access.

* `headers` contains the headers of the request.
* `uri` is the `URI.Info` of the request.
* `query` is the decoded query part of the uri.

Adapters
--------
*Urna* supports various adapters and it's easy to extend them as well.

Adapters are used to deal with encoding and decoding based on the value of
`Accept` and `Content-Type` headers.

The ones provided out of the box are an `application/json` adapter based on
[jazz](https://github.com/meh/jazz) and an `application/x-www-form-urlencoded`
adapter which uses the standard `URI.decode_query` function.

```elixir
defmodule Example do
  use Urna, adapters: [Urna.JSON, Urna.Form]

  resource :foo do
    get do
      [foo: :bar]
    end
  end
end
```

CORS
----
*Urna* supports CORS out of the box, just pass what to allow on `use Urna` and
it will handle the various access control headers automatically.

```elixir
defmodule API do
  use Urna, allow: [methods: true, headers: true, credentials: true]
end
```

This example will allow all methods, headers and HTTP credentials, check the
documentation for more information.