Skip to content

Commit

Permalink
Switch from #req{} to #{}
Browse files Browse the repository at this point in the history
Also drop elli_request:is_request/1.
  • Loading branch information
yurrriq committed May 5, 2018
1 parent 21d1cfd commit 1511d55
Show file tree
Hide file tree
Showing 13 changed files with 199 additions and 118 deletions.
9 changes: 6 additions & 3 deletions README.md
Expand Up @@ -77,22 +77,24 @@ A minimal callback module could look like this:
```erlang
-module(elli_minimal_callback).
-export([handle/2, handle_event/3]).

-include_lib("elli/include/elli.hrl").
-behaviour(elli_handler).


handle(Req, _Args) ->
%% Delegate to our handler function
handle(elli_request:method(Req), elli_request:path(Req), Req).


handle('GET',[<<"hello">>, <<"world">>], _Req) ->
%% Reply with a normal response. `ok' can be used instead of `200'
%% to signal success.
{ok, [], <<"Hello World!">>};


handle(_, _, _Req) ->
{404, [], <<"Not Found">>}.


%% @doc Handle request events, like request completed, exception
%% thrown, client timeout, etc. Must return `ok'.
handle_event(_Event, _Data, _Args) ->
Expand All @@ -111,9 +113,11 @@ your needs.
-export([start_link/0]).
-export([init/1]).


start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).


init([]) ->
ElliOpts = [{callback, fancyapi_callback}, {port, 3000}],
ElliSpec = {
Expand All @@ -123,7 +127,6 @@ init([]) ->
5000,
worker,
[elli]},

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

Expand Down
22 changes: 21 additions & 1 deletion doc/elli_http.md
Expand Up @@ -21,6 +21,26 @@ closed either by the client timing out or explicitly by the user.



### <a name="type-connection_token">connection_token()</a> ###


<pre><code>
connection_token() = {<a href="#type-connection_token_label">connection_token_label()</a>, binary()}
</code></pre>




### <a name="type-connection_token_label">connection_token_label()</a> ###


<pre><code>
connection_token_label() = keep_alive | close
</code></pre>




### <a name="type-version">version()</a> ###


Expand Down Expand Up @@ -69,7 +89,7 @@ timeout, loop to allow code upgrades of this module.
handle_request(Socket, PrevBin, Options, Callback) -&gt; ConnToken
</code></pre>

<ul class="definitions"><li><code>Socket = <a href="elli_tcp.md#type-socket">elli_tcp:socket()</a></code></li><li><code>PrevBin = binary()</code></li><li><code>Options = <a href="proplists.md#type-proplist">proplists:proplist()</a></code></li><li><code>Callback = <a href="elli_handler.md#type-callback">elli_handler:callback()</a></code></li><li><code>ConnToken = {keep_alive | close, binary()}</code></li></ul>
<ul class="definitions"><li><code>Socket = <a href="elli_tcp.md#type-socket">elli_tcp:socket()</a></code></li><li><code>PrevBin = binary()</code></li><li><code>Options = <a href="proplists.md#type-proplist">proplists:proplist()</a></code></li><li><code>Callback = <a href="elli_handler.md#type-callback">elli_handler:callback()</a></code></li><li><code>ConnToken = <a href="#type-connection_token">connection_token()</a></code></li></ul>

Handle a HTTP request that will possibly come on the socket.
Returns the appropriate connection token and any buffer containing (parts of)
Expand Down
106 changes: 87 additions & 19 deletions doc/elli_request.md
Expand Up @@ -24,8 +24,8 @@ http_range() = {First::non_neg_integer(), Last::non_neg_integer()} | {offset, Of
## Function Index ##


<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#async_send_chunk-2">async_send_chunk/2</a></td><td>Send a chunk asynchronously.</td></tr><tr><td valign="top"><a href="#body-1">body/1</a></td><td>Return the <code>body</code>.</td></tr><tr><td valign="top"><a href="#body_qs-1">body_qs/1</a></td><td>Parse <code>application/x-www-form-urlencoded</code> body into a proplist.</td></tr><tr><td valign="top"><a href="#chunk_ref-1">chunk_ref/1</a></td><td>Return a reference that can be used to send chunks to the client.</td></tr><tr><td valign="top"><a href="#close_chunk-1">close_chunk/1</a></td><td>Explicitly close the chunked connection.</td></tr><tr><td valign="top"><a href="#get_arg-2">get_arg/2</a></td><td>Equivalent to <a href="#get_arg-3"><tt>get_arg(Key, Req, undefined)</tt></a>.</td></tr><tr><td valign="top"><a href="#get_arg-3">get_arg/3</a></td><td>Equivalent to <a href="proplists.md#get_value-3"><tt>proplists:get_value(Key, Args, Default)</tt></a>.</td></tr><tr><td valign="top"><a href="#get_arg_decoded-2">get_arg_decoded/2</a></td><td>Equivalent to <a href="#get_arg_decoded-3"><tt>get_arg_decoded(Key, Req, undefined)</tt></a>.</td></tr><tr><td valign="top"><a href="#get_arg_decoded-3">get_arg_decoded/3</a></td><td></td></tr><tr><td valign="top"><a href="#get_args-1">get_args/1</a></td><td>Return a proplist of keys and values of the original query string.</td></tr><tr><td valign="top"><a href="#get_args_decoded-1">get_args_decoded/1</a></td><td></td></tr><tr><td valign="top"><a href="#get_header-2">get_header/2</a></td><td>Equivalent to <a href="proplists.md#get_value-2"><tt>proplists:get_value(Key, Headers)</tt></a>.</td></tr><tr><td valign="top"><a href="#get_header-3">get_header/3</a></td><td>Equivalent to <a href="proplists.md#get_value-3"><tt>proplists:get_value(Key, Headers, Default)</tt></a>.</td></tr><tr><td valign="top"><a href="#get_range-1">get_range/1</a></td><td>Parse the <code>Range</code> header from the request.</td></tr><tr><td valign="top"><a href="#headers-1">headers/1</a></td><td>Return the <code>headers</code>.</td></tr><tr><td valign="top"><a href="#host-1">host/1</a></td><td>Return the <code>host</code>.</td></tr><tr><td valign="top"><a href="#is_request-1">is_request/1</a></td><td></td></tr><tr><td valign="top"><a href="#method-1">method/1</a></td><td>Return the <code>method</code>.</td></tr><tr><td valign="top"><a href="#path-1">path/1</a></td><td>Return <code>path</code> split into binary parts.</td></tr><tr><td valign="top"><a href="#peer-1">peer/1</a></td><td></td></tr><tr><td valign="top"><a href="#port-1">port/1</a></td><td>Return the <code>port</code>.</td></tr><tr><td valign="top"><a href="#post_arg-2">post_arg/2</a></td><td>Equivalent to <a href="#post_arg-3"><tt>post_arg(Key, Req, undefined)</tt></a>.</td></tr><tr><td valign="top"><a href="#post_arg-3">post_arg/3</a></td><td></td></tr><tr><td valign="top"><a href="#post_arg_decoded-2">post_arg_decoded/2</a></td><td>Equivalent to <a href="#post_arg_decoded-3"><tt>post_arg_decoded(Key, Req, undefined)</tt></a>.</td></tr><tr><td valign="top"><a href="#post_arg_decoded-3">post_arg_decoded/3</a></td><td></td></tr><tr><td valign="top"><a href="#post_args-1">post_args/1</a></td><td></td></tr><tr><td valign="top"><a href="#post_args_decoded-1">post_args_decoded/1</a></td><td></td></tr><tr><td valign="top"><a href="#query_str-1">query_str/1</a></td><td>Calculate the query string associated with a given <code>Request</code>
as a binary.</td></tr><tr><td valign="top"><a href="#raw_path-1">raw_path/1</a></td><td>Return the <code>raw_path</code>, i.e.</td></tr><tr><td valign="top"><a href="#scheme-1">scheme/1</a></td><td>Return the <code>scheme</code>.</td></tr><tr><td valign="top"><a href="#send_chunk-2">send_chunk/2</a></td><td>Send a chunk synchronously.</td></tr><tr><td valign="top"><a href="#to_proplist-1">to_proplist/1</a></td><td>Serialize the <code>Req</code>uest record to a proplist.</td></tr></table>
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#async_send_chunk-2">async_send_chunk/2</a></td><td>Send a chunk asynchronously.</td></tr><tr><td valign="top"><a href="#body-1">body/1</a></td><td>Return the <code>body</code>.</td></tr><tr><td valign="top"><a href="#body_qs-1">body_qs/1</a></td><td>Parse <code>application/x-www-form-urlencoded</code> body into a proplist.</td></tr><tr><td valign="top"><a href="#callback-1">callback/1</a></td><td>Return the <code>callback</code>.</td></tr><tr><td valign="top"><a href="#chunk_ref-1">chunk_ref/1</a></td><td>Return a reference that can be used to send chunks to the client.</td></tr><tr><td valign="top"><a href="#close_chunk-1">close_chunk/1</a></td><td>Explicitly close the chunked connection.</td></tr><tr><td valign="top"><a href="#get_arg-2">get_arg/2</a></td><td>Equivalent to <a href="#get_arg-3"><tt>get_arg(Key, Req, undefined)</tt></a>.</td></tr><tr><td valign="top"><a href="#get_arg-3">get_arg/3</a></td><td>Equivalent to <a href="proplists.md#get_value-3"><tt>proplists:get_value(Key, Args, Default)</tt></a>.</td></tr><tr><td valign="top"><a href="#get_arg_decoded-2">get_arg_decoded/2</a></td><td>Equivalent to <a href="#get_arg_decoded-3"><tt>get_arg_decoded(Key, Req, undefined)</tt></a>.</td></tr><tr><td valign="top"><a href="#get_arg_decoded-3">get_arg_decoded/3</a></td><td></td></tr><tr><td valign="top"><a href="#get_args-1">get_args/1</a></td><td>Return a proplist of keys and values of the original query string.</td></tr><tr><td valign="top"><a href="#get_args_decoded-1">get_args_decoded/1</a></td><td></td></tr><tr><td valign="top"><a href="#get_header-2">get_header/2</a></td><td>Equivalent to <a href="proplists.md#get_value-2"><tt>proplists:get_value(Key, Headers)</tt></a>.</td></tr><tr><td valign="top"><a href="#get_header-3">get_header/3</a></td><td>Equivalent to <a href="proplists.md#get_value-3"><tt>proplists:get_value(Key, Headers, Default)</tt></a>.</td></tr><tr><td valign="top"><a href="#get_range-1">get_range/1</a></td><td>Parse the <code>Range</code> header from the request.</td></tr><tr><td valign="top"><a href="#headers-1">headers/1</a></td><td>Return the <code>headers</code>.</td></tr><tr><td valign="top"><a href="#host-1">host/1</a></td><td>Return the <code>host</code>.</td></tr><tr><td valign="top"><a href="#method-1">method/1</a></td><td>Return the <code>method</code>.</td></tr><tr><td valign="top"><a href="#path-1">path/1</a></td><td>Return <code>path</code> split into binary parts.</td></tr><tr><td valign="top"><a href="#peer-1">peer/1</a></td><td></td></tr><tr><td valign="top"><a href="#port-1">port/1</a></td><td>Return the <code>port</code>.</td></tr><tr><td valign="top"><a href="#post_arg-2">post_arg/2</a></td><td>Equivalent to <a href="#post_arg-3"><tt>post_arg(Key, Req, undefined)</tt></a>.</td></tr><tr><td valign="top"><a href="#post_arg-3">post_arg/3</a></td><td></td></tr><tr><td valign="top"><a href="#post_arg_decoded-2">post_arg_decoded/2</a></td><td>Equivalent to <a href="#post_arg_decoded-3"><tt>post_arg_decoded(Key, Req, undefined)</tt></a>.</td></tr><tr><td valign="top"><a href="#post_arg_decoded-3">post_arg_decoded/3</a></td><td></td></tr><tr><td valign="top"><a href="#post_args-1">post_args/1</a></td><td></td></tr><tr><td valign="top"><a href="#post_args_decoded-1">post_args_decoded/1</a></td><td></td></tr><tr><td valign="top"><a href="#query_str-1">query_str/1</a></td><td>Calculate the query string associated with a given <code>Request</code>
as a binary.</td></tr><tr><td valign="top"><a href="#raw_path-1">raw_path/1</a></td><td>Return the <code>raw_path</code>, i.e.</td></tr><tr><td valign="top"><a href="#scheme-1">scheme/1</a></td><td>Return the <code>scheme</code>.</td></tr><tr><td valign="top"><a href="#send_chunk-2">send_chunk/2</a></td><td>Send a chunk synchronously.</td></tr><tr><td valign="top"><a href="#set_body-2">set_body/2</a></td><td>Set the <code>body</code> of <code>Req</code> to <code>Body</code>.</td></tr><tr><td valign="top"><a href="#socket-1">socket/1</a></td><td>Return the <code>socket</code>.</td></tr><tr><td valign="top"><a href="#to_proplist-1">to_proplist/1</a></td><td>Serialize the <code>Req</code>uest record to a proplist.</td></tr><tr><td valign="top"><a href="#version-1">version/1</a></td><td>Return the <code>version</code>.</td></tr></table>


<a name="functions"></a>
Expand All @@ -44,7 +44,10 @@ Send a chunk asynchronously.

### body/1 ###

`body(Req) -> any()`
<pre><code>
body(X1::<a href="elli.md#type-req">elli:req()</a>) -&gt; <a href="elli.md#type-body">elli:body()</a>
</code></pre>
<br />

Return the `body`.

Expand All @@ -56,6 +59,17 @@ Return the `body`.

Parse `application/x-www-form-urlencoded` body into a proplist.

<a name="callback-1"></a>

### callback/1 ###

<pre><code>
callback(X1::<a href="elli.md#type-req">elli:req()</a>) -&gt; <a href="elli_handler.md#type-callback">elli_handler:callback()</a>
</code></pre>
<br />

Return the `callback`.

<a name="chunk_ref-1"></a>

### chunk_ref/1 ###
Expand Down Expand Up @@ -111,7 +125,7 @@ Equivalent to [`get_arg_decoded(Key, Req, undefined)`](#get_arg_decoded-3).
### get_args/1 ###

<pre><code>
get_args(Req::<a href="elli.md#type-req">elli:req()</a>) -&gt; QueryArgs::<a href="proplists.md#type-proplist">proplists:proplist()</a>
get_args(X1::<a href="elli.md#type-req">elli:req()</a>) -&gt; QueryArgs::<a href="proplists.md#type-proplist">proplists:proplist()</a>
</code></pre>
<br />

Expand Down Expand Up @@ -158,51 +172,63 @@ Use [`elli_util:normalize_range/2`](elli_util.md#normalize_range-2) to get a val

### headers/1 ###

`headers(Req) -> any()`
<pre><code>
headers(X1::<a href="elli.md#type-req">elli:req()</a>) -&gt; <a href="elli.md#type-headers">elli:headers()</a>
</code></pre>
<br />

Return the `headers`.

<a name="host-1"></a>

### host/1 ###

`host(Req) -> any()`
<pre><code>
host(X1::<a href="elli.md#type-req">elli:req()</a>) -&gt; undefined | binary()
</code></pre>
<br />

Return the `host`.

<a name="is_request-1"></a>

### is_request/1 ###

`is_request(Req) -> any()`

<a name="method-1"></a>

### method/1 ###

`method(Req) -> any()`
<pre><code>
method(X1::<a href="elli.md#type-req">elli:req()</a>) -&gt; <a href="elli.md#type-http_method">elli:http_method()</a>
</code></pre>
<br />

Return the `method`.

<a name="path-1"></a>

### path/1 ###

`path(Req) -> any()`
<pre><code>
path(X1::<a href="elli.md#type-req">elli:req()</a>) -&gt; [binary()]
</code></pre>
<br />

Return `path` split into binary parts.

<a name="peer-1"></a>

### peer/1 ###

`peer(Req) -> any()`
<pre><code>
peer(Req::<a href="elli.md#type-req">elli:req()</a>) -&gt; undefined | binary()
</code></pre>
<br />

<a name="port-1"></a>

### port/1 ###

`port(Req) -> any()`
<pre><code>
port(X1::<a href="elli.md#type-req">elli:req()</a>) -&gt; undefined | 1..65535
</code></pre>
<br />

Return the `port`.

Expand Down Expand Up @@ -262,15 +288,21 @@ as a binary.

### raw_path/1 ###

`raw_path(Req) -> any()`
<pre><code>
raw_path(X1::<a href="elli.md#type-req">elli:req()</a>) -&gt; binary()
</code></pre>
<br />

Return the `raw_path`, i.e. not split or parsed for query params.

<a name="scheme-1"></a>

### scheme/1 ###

`scheme(Req) -> any()`
<pre><code>
scheme(X1::<a href="elli.md#type-req">elli:req()</a>) -&gt; undefined | binary()
</code></pre>
<br />

Return the `scheme`.

Expand All @@ -284,12 +316,48 @@ Send a chunk synchronously.
If the referenced process is dead, return early with `{error, closed}`,
instead of timing out.

<a name="set_body-2"></a>

### set_body/2 ###

<pre><code>
set_body(Req::<a href="elli.md#type-req">elli:req()</a>, Body::<a href="elli.md#type-body">elli:body()</a>) -&gt; <a href="elli.md#type-req">elli:req()</a>
</code></pre>
<br />

Set the `body` of `Req` to `Body`.

<a name="socket-1"></a>

### socket/1 ###

<pre><code>
socket(X1::<a href="elli.md#type-req">elli:req()</a>) -&gt; undefined | <a href="elli_tcp.md#type-socket">elli_tcp:socket()</a>
</code></pre>
<br />

Return the `socket`.

<a name="to_proplist-1"></a>

### to_proplist/1 ###

`to_proplist(Req) -> any()`
<pre><code>
to_proplist(Req::<a href="elli.md#type-req">elli:req()</a>) -&gt; <a href="proplists.md#type-proplist">proplists:proplist()</a>
</code></pre>
<br />

Serialize the `Req`uest record to a proplist.
Useful for logging.

<a name="version-1"></a>

### version/1 ###

<pre><code>
version(Req::<a href="elli.md#type-req">elli:req()</a>) -&gt; <a href="elli_http.md#type-version">elli_http:version()</a>
</code></pre>
<br />

Return the `version`.

17 changes: 0 additions & 17 deletions include/elli.hrl

This file was deleted.

2 changes: 1 addition & 1 deletion src/elli.app.src
@@ -1,7 +1,7 @@
{application, elli,
[
{description, "Erlang web server for HTTP APIs"},
{vsn, "3.0.0"},
{vsn, "4.0.0"},
{modules, [
elli,
elli_example_callback,
Expand Down
17 changes: 15 additions & 2 deletions src/elli.erl
Expand Up @@ -7,7 +7,7 @@
%%
-module(elli).
-behaviour(gen_server).
-include("elli.hrl").
-include("elli_conf.hrl").
-include("elli_util.hrl").

%% API
Expand All @@ -27,7 +27,20 @@
-export_type([req/0, http_method/0, body/0, headers/0, response_code/0]).

%% @type req(). A record representing an HTTP request.
-type req() :: #req{}.
-type req() :: #{method => elli:http_method(),
scheme => undefined | binary(),
host => undefined | binary(),
port => undefined | 1..65535,
path => [binary()],
args => [{binary(), any()}],
raw_path => binary(),
version => elli_http:version(),
headers => elli:headers(),
body => elli:body(),
pid => pid(),
socket => undefined | elli_tcp:socket(),
callback => elli_handler:callback()
}.

%% @type http_method(). An uppercase atom representing a known HTTP verb or a
%% binary for other verbs.
Expand Down
2 changes: 2 additions & 0 deletions src/elli_conf.hrl
@@ -0,0 +1,2 @@
-define(EXAMPLE_CONF, [{callback, elli_example_callback},
{callback_args, []}]).
1 change: 0 additions & 1 deletion src/elli_example_callback.erl
Expand Up @@ -10,7 +10,6 @@
-export([handle/2, handle_event/3]).
-export([chunk_loop/1]).

-include("elli.hrl").
-include("elli_util.hrl").
-behaviour(elli_handler).

Expand Down
13 changes: 6 additions & 7 deletions src/elli_http.erl
Expand Up @@ -4,7 +4,6 @@
%% connects. It then handles requests on that connection until it's
%% closed either by the client timing out or explicitly by the user.
-module(elli_http).
-include("elli.hrl").
-include("elli_util.hrl").


Expand Down Expand Up @@ -596,11 +595,11 @@ do_check_max_size_x2(_, _, _, _) -> ok.
mk_req(Method, PathTuple, Headers, Body, V, Socket, {Mod, Args} = Callback) ->
case parse_path(PathTuple) of
{ok, {Scheme, Host, Port}, {Path, URL, URLArgs}} ->
#req{method = Method, scheme = Scheme, host = Host,
port = Port, path = URL, args = URLArgs,
version = V, raw_path = Path, headers = Headers,
body = Body, pid = self(), socket = Socket,
callback = Callback};
#{method => Method, scheme => Scheme, host => Host,
port => Port, path => URL, args => URLArgs,
version => V, raw_path => Path, headers => Headers,
body => Body, pid => self(), socket => Socket,
callback => Callback};
{error, Reason} ->
handle_event(Mod, request_parse_error,
[{Reason, {Method, PathTuple}}], Args),
Expand All @@ -612,7 +611,7 @@ mk_req(Method, PathTuple, Headers, Body, V, Socket, {Mod, Args} = Callback) ->

mk_req(Method, Scheme, Host, Port, PathTuple, Headers, Body, V, Socket, Callback) ->
Req = mk_req(Method, PathTuple, Headers, Body, V, Socket, Callback),
Req#req{scheme = Scheme, host = Host, port = Port}.
Req#{scheme := Scheme, host := Host, port := Port}.


%%
Expand Down

0 comments on commit 1511d55

Please sign in to comment.