Browse Source

Merge branch 'rest_post_created_path' of https://github.com/treetopllc/cowboy

Loïc Hoguin 12 years ago
parent
commit
ec52b4f4df
3 changed files with 69 additions and 0 deletions
  1. 19 0
      src/cowboy_rest.erl
  2. 15 0
      test/http_SUITE.erl
  3. 35 0
      test/rest_created_path_resource.erl

+ 19 - 0
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) ->

+ 15 - 0
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">>,

+ 35 - 0
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}.
+
+