knutin / elli

Simple, robust and performant Erlang web server
MIT License
663 stars 79 forks source link

Help: Failing to add middleware #87

Closed rossjones closed 9 years ago

rossjones commented 9 years ago

Sorry for asking for help in a ticket, I couldn't see anywhere else to ask :( Yet more apologies if it's obvious, my first erlang app ...

I'm trying to add some cors headers to all requests going through my API. My cors_middleware.erl looks like

-module(cors_middleware).
-export([postprocess/3]).

postprocess(_Req, {ResponseCode, Headers, Body}, _Args) ->
    {ResponseCode, cors_headers() ++ Headers, Body}.

cors_headers() ->
    [{<<"Access-Control-Allow-Origin">>, <<"*">>},
    {<<"access-control-allow-methods">>, <<"GET,HEAD,POST,DELETE,OPTIONS,PUT">>},
    {<<"access-control-allow-headers">>, <<"Content-type">>}].

and my supervisor as follows (munged from the README and the elli_middleware.erl doc.

init([]) ->
    Config = [{mods, [{cors_middleware, []}]}],
    ElliConfig = [{callback, eric_callback},
                  {callback_args, Config},
                  {port, 3000}],

    ElliSpec = {
        eric,
        {elli, start_link, [ElliConfig]},
        permanent,
        5000,
        worker,
        [elli]},

    {ok, { {one_for_one, 5, 10}, [ElliSpec]} }.

Yes, my app is called eric. Whilst all my callbacks work, the middleware doesn't seem to get executed :(

knutin commented 9 years ago

Hey. No worries about creating a ticket. It's also okay if you email me directly at knutin@gmail.com. Maybe I should put that in the readme..

It looks like the problem is that the middleware is never executed. In the code you posted, elli is started with eric_callback as the callback module when it should instead be elli_middleware. (elli_middleware is actually just a normal handler that delegates to other handlers)

I think you want something like this:

init([]) ->
    Config = [{mods, [{cors_middleware, []}, {eric_callback, []]}],
    ElliConfig = [{callback, elli_middleware},
                  {callback_args, Config},
                  {port, 3000}],
    ...

Since you are using postprocess/3 you need the real callback to execute first, then your middleware. By listing your middleware before your handler you achieve that.

The documentation is not great. I'm very happy to accept pull requests also for documentation improvements. :)

rossjones commented 9 years ago

Thanks for the quick response, that both solved my problem and made it a lot clearer. Once I've got everything up and running I'll blog about it and see if I can formulate some documentation too :) I found out about elli via https://www.youtube.com/watch?v=xCjWXJ1j64M