Packages
raxx
0.2.0
1.1.0
1.0.1
1.0.0
1.0.0-rc.3
1.0.0-rc.2
retired
1.0.0-rc.1
retired
1.0.0-rc.0
retired
0.18.1
0.18.0
0.17.6
0.17.5
0.17.4
0.17.3
0.17.2
0.17.1
0.17.0
0.16.1
0.16.0
retired
0.15.11
0.15.10
0.15.9
0.15.8
0.15.7
0.15.6
0.15.5
0.15.4
0.15.3
0.15.2
0.15.1
0.15.0
0.14.14
0.14.13
0.14.12
0.14.11
0.14.10
0.14.9
0.14.8
0.14.7
0.14.6
0.14.5
0.14.4
0.14.3
0.14.2
0.14.1
0.14.0
0.13.0
0.12.3
0.12.2
0.12.1
0.12.0
0.11.1
0.11.0
0.10.5
0.10.4
0.10.3
0.10.2
0.10.1
0.10.0
0.9.0
0.8.2
0.8.1
0.8.0
0.7.1
0.7.0
0.6.0
0.5.2
0.5.1
0.5.0
0.4.3
0.4.2
0.4.1
0.4.0
0.3.0
0.2.0
0.1.0
0.0.1
Interface for HTTP webservers, frameworks and clients.
Current section
Files
Jump to
Current section
Files
README.md
# Raxx: an Elixir webserver interface
## What is Raxx?
1. An interface specification for Elixir webservers and Elixir application.
2. A set of tools to help develop Raxx-compliant web applications
*Raxx is inspired by the [Ruby's Rack interface](http://rack.github.io/) and [Clojure's Ring interface](https://github.com/ring-clojure).*
[Documentation for Raxx is available online](TODO hex)
## Usage
### Raxx handlers
A Raxx handler is a module that has a `handle_request` function.
It takes two arguments, a raxx request and an application specific environment.
The return value is a map with three keys, the status, the headers, and the body.
### Minimal
With the power of Elixirs pattern matching against maps it is possible to handle request routing without a dsl.
```elixir
defmodule BasicRouter do
# handle the root path
def handle_request(%{path: [], method: "GET"}, _env) do
%{status: 200, headers: %{}, body: "Hello, World!"}
end
# forward to a sub router
def handle_request(request = %{path: ["api" | rest]}, env) do
ApiRouter.handle_request(%{request | path: rest}, env)
end
# handle a variable segment in path
def handle_request(%{path: ["greet", name], method: "GET"}, _env) do
%{status: 200, headers: %{}, body: "Hello, #{name}"}
end
end
```
Manually creating all these response hashes can be tedious so the Response module has helpers.
```elixir
defmodule FooRouter do
import Raxx.Response
def handle_request(%{path: ["users"], method: "GET"}, _env) do
ok("All user: Andy, Bethany, Clive")
end
def handle_request(%{path: ["users"], method: "POST", body: data}, _env) do
case MyApp.create_user(data) do
{:ok, user} -> created("New user #{user}")
{:error, :already_exists} -> conflict("sorry")
{:error, :bad_params} -> bad_request("sorry")
{:error, :database_fail} -> bad_gateway("sorry")
{:error, _unknown} -> internal_server_error("Well thats weird")
end
end
def handle_request(%{path: ["users"], method: _}, _env) do
method_not_allowed("Don't do that")
end
def handle_request(%{path: ["users", id], method: "GET"}, _env) do
case MyApp.get_user(id) do
{:ok, user} -> ok("New user #{user}")
{:error, nil} -> not_found("User unknown")
{:error, :deleted} -> gone("User deleted")
end
end
def handle_request(_request, _env) do
not_found("Sorry didn't get that")
end
end
```
### Raxx Server Sent Events
See sever sent events in examples directory.
```elixir
defmodule ServerSentEvents.Router do
import Raxx.Response
# Can't use ServerSentEvents Handler in same module as other Streaming handlers.
import Raxx.ServerSentEvents
def handle_request(%{path: [], method: "GET"}, _opts) do
ok(home_page)
end
def handle_request(%{path: ["events"], method: "GET"}, opts) do
upgrade(opts, __MODULE__)
end
def handle_request(_request, _opts) do
not_found("Page not found")
end
def handle_upgrade(_options) do
Process.send_after(self, 0, 1000)
event("hello")
end
def handle_info(10, _opts) do
close()
end
def handle_info(i, _opts) when rem(i, 2) == 0 do
Process.send_after(self, i + 1, 1000)
event(Integer.to_string(i))
end
def handle_info(i, _opts) do
Process.send_after(self, i + 1, 1000)
no_event
end
defp home_page do
"""
The page. see example.
"""
end
end
```
Some outstanding questions about Server Sent Events functionality.
- [ ] Disallow event of type error.
- [ ] Handle long poll pollyfill.
- [ ] Raxx client.
- [ ] Any shared functionality with file streaming, long pole.
- [ ] What to do if message handler throws error.
[Link to implementing server in node.js](http://www.html5rocks.com/en/tutorials/eventsource/basics/)
[HTML living standard](https://html.spec.whatwg.org/multipage/comms.html#server-sent-events)
## Installation
If [available in Hex](https://hex.pm/docs/publish), the package can be installed as:
1. Add raxx to your list of dependencies in `mix.exs`:
def deps do
[{:raxx, "~> 0.0.1"}]
end
2. Raxx apps/routers needs to be mounted Elixir/erlang server using one of the provided adapters. Instructions for this are found in each adapters README
- [cowboy](https://github.com/CrowdHailer/raxx/tree/master/example/cowboy_example). Currently just follow example.
## Contributing
If you have Elixir installed on your machine then you can treat this project as a normal mix project and run tests via `mix test`.
If required a development environment can be created using [Vagrant](www.vagrantup.com).
### Principles
- Stateless HTTP request fulfill a valuable role in modern applications and will continue to do so.
- Handling other communication patterns as plug intends to do just adds complexity which is unnecessary on a whole class of applications.
- Use Ruby rack and Clojure ring as inspiration for naming but be happy to break away from historic CGI-style header names.
- Surface utilities so that it can be used in general HTTP based applications
- Only return json if json is asked for.
- [Your server as a function](https://monkey.org/~marius/funsrv.pdf)