aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/basic_auth/README.md5
-rw-r--r--examples/basic_auth/src/basic_auth_app.erl6
-rw-r--r--src/cowboy_http.erl37
-rw-r--r--src/cowboy_rest.erl19
-rw-r--r--test/http_SUITE.erl15
-rw-r--r--test/rest_created_path_resource.erl35
6 files changed, 92 insertions, 25 deletions
diff --git a/examples/basic_auth/README.md b/examples/basic_auth/README.md
index 74662cd..38ae9a2 100644
--- a/examples/basic_auth/README.md
+++ b/examples/basic_auth/README.md
@@ -1,5 +1,5 @@
-Cowboy Basic Authorization Rest Hello World.
-============================================
+Cowboy Basic Authorization Rest Hello World
+===========================================
To compile this example you need rebar in your PATH.
@@ -41,4 +41,3 @@ content-type: text/plain
Hello, Alladin!
```
-
diff --git a/examples/basic_auth/src/basic_auth_app.erl b/examples/basic_auth/src/basic_auth_app.erl
index c60a574..24c766e 100644
--- a/examples/basic_auth/src/basic_auth_app.erl
+++ b/examples/basic_auth/src/basic_auth_app.erl
@@ -11,11 +11,11 @@
%% API.
start(_Type, _Args) ->
- Dispatch = [
+ Dispatch = cowboy_router:compile([
{'_', [
- {[], toppage_handler, []}
+ {"/", toppage_handler, []}
]}
- ],
+ ]),
{ok, _} = cowboy:start_http(http, 100, [{port, 8080}], [
{env, [{dispatch, Dispatch}]}
]),
diff --git a/src/cowboy_http.erl b/src/cowboy_http.erl
index 67d3f70..a78e090 100644
--- a/src/cowboy_http.erl
+++ b/src/cowboy_http.erl
@@ -802,6 +802,23 @@ qvalue(<< C, Rest/binary >>, Fun, Q, M)
qvalue(Data, Fun, Q, _M) ->
Fun(Data, Q).
+%% @doc Parse authorization value according rfc 2617.
+%% Only Basic authorization is supported so far.
+-spec authorization(binary(), binary()) -> {binary(), any()} | {error, badarg}.
+authorization(UserPass, Type = <<"basic">>) ->
+ cowboy_http:whitespace(UserPass,
+ fun(D) ->
+ authorization_basic_userid(base64:mime_decode(D),
+ fun(Rest, Userid) ->
+ authorization_basic_password(Rest,
+ fun(Password) ->
+ {Type, {Userid, Password}}
+ end)
+ end)
+ end);
+authorization(String, Type) ->
+ {Type, String}.
+
%% @doc Parse user credentials.
-spec authorization_basic_userid(binary(), fun()) -> any().
authorization_basic_userid(Data, Fun) ->
@@ -831,23 +848,6 @@ authorization_basic_password(<<>>, Fun, Acc) ->
authorization_basic_password(<<C, Rest/binary>>, Fun, Acc) ->
authorization_basic_password(Rest, Fun, <<Acc/binary, C>>).
-%% @doc Parse authorization value according rfc 2617.
-%% Only Basic authorization is supported so far.
--spec authorization(binary(), binary()) -> {binary(), any()} | {error, badarg}.
-authorization(UserPass, Type = <<"basic">>) ->
- cowboy_http:whitespace(UserPass,
- fun(D) ->
- authorization_basic_userid(base64:mime_decode(D),
- fun(Rest, Userid) ->
- authorization_basic_password(Rest,
- fun(Password) ->
- {Type, {Userid, Password}}
- end)
- end)
- end);
-authorization(String, Type) ->
- {Type, String}.
-
%% Decoding.
%% @doc Decode a stream of chunks.
@@ -1350,7 +1350,6 @@ http_authorization_test_() ->
authorization(<<"_[]@#$%^&*()-AA==">>, <<"basic">>)),
?_assertEqual({error, badarg},
authorization(<<"dXNlcjpwYXNzCA==">>, <<"basic">>)) %% user:pass\010
- ].
-
+ ].
-endif.
diff --git a/src/cowboy_rest.erl b/src/cowboy_rest.erl
index fb7f2e1..8967b1d 100644
--- a/src/cowboy_rest.erl
+++ b/src/cowboy_rest.erl
@@ -670,6 +670,8 @@ post_is_create(Req, State) ->
%% (including the leading /).
create_path(Req, State) ->
case call(Req, State, create_path) of
+ no_call ->
+ put_resource(Req, State, fun created_path/2);
{halt, Req2, HandlerState} ->
terminate(Req2, State#state{handler_state=HandlerState});
{Path, Req2, HandlerState} ->
@@ -681,6 +683,23 @@ create_path(Req, State) ->
State2, 303)
end.
+%% Called after content_types_accepted is called for POST methods
+%% when create_path did not exist. Expects the full path to
+%% be returned and MUST exist in the case that create_path
+%% does not.
+created_path(Req, State) ->
+ case call(Req, State, created_path) of
+ {halt, Req2, HandlerState} ->
+ terminate(Req2, State#state{handler_state=HandlerState});
+ {Path, Req2, HandlerState} ->
+ {HostURL, Req3} = cowboy_req:host_url(Req2),
+ State2 = State#state{handler_state=HandlerState},
+ Req4 = cowboy_req:set_resp_header(
+ <<"Location">>, << HostURL/binary, Path/binary >>, Req3),
+ respond(cowboy_req:set_meta(put_path, Path, Req4),
+ State2, 303)
+ end.
+
%% process_post should return true when the POST body could be processed
%% and false when it hasn't, in which case a 500 error is sent.
process_post(Req, State) ->
diff --git a/test/http_SUITE.erl b/test/http_SUITE.erl
index 492863f..0b35cf3 100644
--- a/test/http_SUITE.erl
+++ b/test/http_SUITE.erl
@@ -50,6 +50,7 @@
-export([onresponse_reply/1]).
-export([pipeline/1]).
-export([rest_bad_accept/1]).
+-export([rest_created_path/1]).
-export([rest_expires/1]).
-export([rest_keepalive/1]).
-export([rest_keepalive_post/1]).
@@ -112,6 +113,7 @@ groups() ->
nc_zero,
pipeline,
rest_bad_accept,
+ rest_created_path,
rest_expires,
rest_keepalive,
rest_keepalive_post,
@@ -334,6 +336,7 @@ init_dispatch(Config) ->
{"/missing_put_callbacks", rest_missing_callbacks, []},
{"/nodelete", rest_nodelete_resource, []},
{"/patch", rest_patch_resource, []},
+ {"/created_path", rest_created_path_resource, []},
{"/resetags", rest_resource_etags, []},
{"/rest_expires", rest_expires, []},
{"/loop_timeout", http_handler_loop_timeout, []},
@@ -763,6 +766,18 @@ rest_bad_accept(Config) ->
Client),
{ok, 400, _, _} = cowboy_client:response(Client2).
+rest_created_path(Config) ->
+ Headers = [{<<"content-type">>, <<"text/plain">>}],
+ Body = <<"Whatever">>,
+ Client = ?config(client, Config),
+ URL = build_url("/created_path", Config),
+ {ok, Client2} = cowboy_client:request(<<"POST">>, URL, Headers,
+ Body, Client),
+ {ok, 303, ResHeaders, _} = cowboy_client:response(Client2),
+ {<<"location">>, _Location} =
+ lists:keyfind(<<"location">>, 1, ResHeaders),
+ ok.
+
rest_expires(Config) ->
Client = ?config(client, Config),
{ok, Client2} = cowboy_client:request(<<"GET">>,
diff --git a/test/rest_created_path_resource.erl b/test/rest_created_path_resource.erl
new file mode 100644
index 0000000..5ad8cfc
--- /dev/null
+++ b/test/rest_created_path_resource.erl
@@ -0,0 +1,35 @@
+-module(rest_created_path_resource).
+-export([init/3]).
+-export([allowed_methods/2]).
+-export([content_types_provided/2]).
+-export([get_text_plain/2]).
+-export([post_is_create/2]).
+-export([content_types_accepted/2]).
+-export([post_text_plain/2]).
+-export([created_path/2]).
+
+init(_Transport, _Req, _Opts) ->
+ {upgrade, protocol, cowboy_rest}.
+
+allowed_methods(Req, State) ->
+{[<<"HEAD">>, <<"GET">>, <<"POST">>], Req, State}.
+
+content_types_provided(Req, State) ->
+ {[{{<<"text">>, <<"plain">>, []}, get_text_plain}], Req, State}.
+
+get_text_plain(Req, State) ->
+ {<<"This is REST!">>, Req, State}.
+
+post_is_create(Req, State) ->
+ {true, Req, State}.
+
+content_types_accepted(Req, State) ->
+ {[{{<<"text">>, <<"plain">>, []}, post_text_plain}], Req, State}.
+
+post_text_plain(Req, State) ->
+ {true, Req, State}.
+
+created_path(Req, State) ->
+ {<<"/created">>, Req, State}.
+
+