I am using elli https://github.com/knutin/elli in my Elixir application.
The sample code is provided below. It is quite basic, every time it is run, I only get "Internal Server Error". I am not sure what I am doing wrong. Can any one please help ?
defmodule Client.TestHttp do
@behaviour :elli_handler
def handle(_Req,_Args) do
handle(:elli_request.method(Req), :elli_request.path(Req),Args)
end
def handle_event(_,_,_)do
:ok
end
def handle(:GET,[],_)do
{:ok, [], "OkGet"}
end
end
This is how I am executing
{:ok,pid}=:elli.start_link [callback: Client.TestHttp, port: 2020]
It looks like you haven't fully translated the Erlang code from the example and are still using variables that begin with an uppercase letter.
Change handle to:
def handle(req, args) do
handle(:elli_request.method(req), :elli_request.path(req), args)
end
Notice the difference in the variable names. In Elixir, variables are written in snake_case
and modules in CamelCase
. Using and underscore (_
) such as _var
in a match indicates that the variable is unused.
Your code would actually be expanding Req
and Args
to atoms due to module names in Elixir being atoms:
Req == :'Elixir.Req' # true
In addition to the answers above, I would like to write up a complete guide on getting knutin/elli
to work with Elixir.
The above answers are correct, but I needed some more information to get up and running in my new elixir project.
Implement a handler that has @behaviour :elli_handler
This is your router/controller. A bare minimum example version of this looks like this:
# lib/elli_handler.ex
defmodule ElliHandler do
@behaviour :elli_handler
alias :elli_request, as: Request
def handle(req, args) do
handle(Request.method(req), Request.path(req), req, args)
end
def handle(:GET, _, req, args) do
# do something with the request.
# e.g. you can use Request.get_arg/2 to fetch a query param
say = Request.get_arg("say", req)
# Return a tuple with 3 elements
# status code, list of header tuples, response body
{200, [], "echo, #{say}"}
end
# Here you can react to all kinds of events of the full connection/request/response cycle
# You must implement this, otherwise elli wont function properly, as it evaluates
# the return value of handle_event/3.
def handle_event(event, args, config) do
# Here would be a good point to handle logging.
# IO.inspect([event, args, config])
:ok
end
end
Lets use an app that starts an elli supervisor
# lib/elli_supervisor.ex
defmodule ElliSupervisor do
use Supervisor
def start_link(ref, options) do
Supervisor.start_link(__MODULE__, options, name: ref)
end
def init(options) do
children = [
worker(:elli, [options], id: :elli_http_server)
]
supervise(children, strategy: :one_for_one)
end
def shutdown(ref) do
case Supervisor.terminate_child(ref, :elli_http_server) do
:ok -> Supervisor.delete_child(ref, :elli_http_server)
err -> err
end
end
end
# lib/app.ex
defmodule App do
use Application
def start(_type, _args) do
import Supervisor.Spec, warn: false
# lets start our elli supervisor, setting its options
# callback should be set to the elli handler that implements the elli_handler behaviour
# port will be the port elli is listening on, defaults to 8080
ElliSupervisor.start_link(__MODULE__, callback: ElliHandler, port: 3000)
end
end
# in mix.exs
def application do
[
mod: {App, []}
]
end
Add elli as a dependency to your mix.exs
Run mix get.deps
to install your dependencies.
Start your server with mix run --no-halt
or in a console using iex -S mix
.
# in mix.exs
defp deps do
[
# elli is our web server layer
{:elli, github: "knutin/elli"}
]
end
In addition to @Gazier's answer (which is correct, of course), your code also looks wrong in another way. In your original source you've got:
def handle(_Req,_Args) do
handle(:elli_request.method(Req), :elli_request.path(Req),Args)
end
The parameter to the call to :elli_request.method
would need to be _Req
and the parameters to the :elli_request.path
would also need to be _Req
and _Args
. If variables starting with an uppercase letter were correct (they're not) it would look like this:
def handle(_Req,_Args) do
handle(:elli_request.method(_Req), :elli_request.path(_Req),_Args)
end
But as Gazier pointed out your variables are not correctly cased anyway.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With