aboutsummaryrefslogtreecommitdiffstats
path: root/src/cowboy_http_rest.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/cowboy_http_rest.erl')
-rw-r--r--src/cowboy_http_rest.erl113
1 files changed, 73 insertions, 40 deletions
diff --git a/src/cowboy_http_rest.erl b/src/cowboy_http_rest.erl
index 35f82e3..e6cc6ff 100644
--- a/src/cowboy_http_rest.erl
+++ b/src/cowboy_http_rest.erl
@@ -53,7 +53,8 @@
%% You do not need to call this function manually. To upgrade to the REST
%% protocol, you simply need to return <em>{upgrade, protocol, {@module}}</em>
%% in your <em>cowboy_http_handler:init/3</em> handler function.
--spec upgrade(pid(), module(), any(), #http_req{}) -> {ok, #http_req{}}.
+-spec upgrade(pid(), module(), any(), #http_req{})
+ -> {ok, #http_req{}} | close.
upgrade(_ListenerPid, Handler, Opts, Req) ->
try
case erlang:function_exported(Handler, rest_init, 2) of
@@ -73,7 +74,7 @@ upgrade(_ListenerPid, Handler, Opts, Req) ->
"** Request was ~p~n** Stacktrace: ~p~n~n",
[Handler, Class, Reason, Opts, Req, erlang:get_stacktrace()]),
{ok, _Req2} = cowboy_http_req:reply(500, Req),
- ok
+ close
end.
service_available(Req, State) ->
@@ -88,8 +89,10 @@ known_methods(Req=#http_req{method=Method}, State) ->
next(Req, State, fun uri_too_long/2);
no_call ->
next(Req, State, 501);
- {List, Req2, HandlerState2} ->
- State2 = State#state{handler_state=HandlerState2},
+ {halt, Req2, HandlerState} ->
+ terminate(Req2, State#state{handler_state=HandlerState});
+ {List, Req2, HandlerState} ->
+ State2 = State#state{handler_state=HandlerState},
case lists:member(Method, List) of
true -> next(Req2, State2, fun uri_too_long/2);
false -> next(Req2, State2, 501)
@@ -106,8 +109,10 @@ allowed_methods(Req=#http_req{method=Method}, State) ->
next(Req, State, fun malformed_request/2);
no_call ->
method_not_allowed(Req, State, ['GET', 'HEAD']);
- {List, Req2, HandlerState2} ->
- State2 = State#state{handler_state=HandlerState2},
+ {halt, Req2, HandlerState} ->
+ terminate(Req2, State#state{handler_state=HandlerState});
+ {List, Req2, HandlerState} ->
+ State2 = State#state{handler_state=HandlerState},
case lists:member(Method, List) of
true -> next(Req2, State2, fun malformed_request/2);
false -> method_not_allowed(Req2, State2, List)
@@ -137,12 +142,14 @@ is_authorized(Req, State) ->
case call(Req, State, is_authorized) of
no_call ->
forbidden(Req, State);
- {true, Req2, HandlerState2} ->
- forbidden(Req2, State#state{handler_state=HandlerState2});
- {{false, AuthHead}, Req2, HandlerState2} ->
+ {halt, Req2, HandlerState} ->
+ terminate(Req2, State#state{handler_state=HandlerState});
+ {true, Req2, HandlerState} ->
+ forbidden(Req2, State#state{handler_state=HandlerState});
+ {{false, AuthHead}, Req2, HandlerState} ->
{ok, Req3} = cowboy_http_req:set_resp_header(
<<"Www-Authenticate">>, AuthHead, Req2),
- respond(Req3, State#state{handler_state=HandlerState2}, 401)
+ respond(Req3, State#state{handler_state=HandlerState}, 401)
end.
forbidden(Req, State) ->
@@ -162,8 +169,12 @@ valid_entity_length(Req, State) ->
%% If you need to add additional headers to the response at this point,
%% you should do it directly in the options/2 call using set_resp_headers.
options(Req=#http_req{method='OPTIONS'}, State) ->
- {ok, Req2, HandlerState2} = call(Req, State, options),
- respond(Req2, State#state{handler_state=HandlerState2}, 200);
+ case call(Req, State, options) of
+ {halt, Req2, HandlerState} ->
+ terminate(Req2, State#state{handler_state=HandlerState});
+ {ok, Req2, HandlerState} ->
+ respond(Req2, State#state{handler_state=HandlerState}, 200)
+ end;
options(Req, State) ->
content_types_provided(Req, State).
@@ -186,6 +197,8 @@ content_types_provided(Req=#http_req{meta=Meta}, State) ->
case call(Req, State, content_types_provided) of
no_call ->
not_acceptable(Req, State);
+ {halt, Req2, HandlerState} ->
+ terminate(Req2, State#state{handler_state=HandlerState});
{[], Req2, HandlerState} ->
not_acceptable(Req2, State#state{handler_state=HandlerState});
{CTP, Req2, HandlerState} ->
@@ -280,10 +293,12 @@ languages_provided(Req, State) ->
case call(Req, State, languages_provided) of
no_call ->
charsets_provided(Req, State);
- {[], Req2, HandlerState2} ->
- not_acceptable(Req2, State#state{handler_state=HandlerState2});
- {LP, Req2, HandlerState2} ->
- State2 = State#state{handler_state=HandlerState2, languages_p=LP},
+ {halt, Req2, HandlerState} ->
+ terminate(Req2, State#state{handler_state=HandlerState});
+ {[], Req2, HandlerState} ->
+ not_acceptable(Req2, State#state{handler_state=HandlerState});
+ {LP, Req2, HandlerState} ->
+ State2 = State#state{handler_state=HandlerState, languages_p=LP},
{AcceptLanguage, Req3} =
cowboy_http_req:parse_header('Accept-Language', Req2),
case AcceptLanguage of
@@ -341,10 +356,12 @@ charsets_provided(Req, State) ->
case call(Req, State, charsets_provided) of
no_call ->
set_content_type(Req, State);
- {[], Req2, HandlerState2} ->
- not_acceptable(Req2, State#state{handler_state=HandlerState2});
- {CP, Req2, HandlerState2} ->
- State2 = State#state{handler_state=HandlerState2, charsets_p=CP},
+ {halt, Req2, HandlerState} ->
+ terminate(Req2, State#state{handler_state=HandlerState});
+ {[], Req2, HandlerState} ->
+ not_acceptable(Req2, State#state{handler_state=HandlerState});
+ {CP, Req2, HandlerState} ->
+ State2 = State#state{handler_state=HandlerState, charsets_p=CP},
{AcceptCharset, Req3} =
cowboy_http_req:parse_header('Accept-Charset', Req2),
case AcceptCharset of
@@ -579,12 +596,14 @@ is_put_to_missing_resource(Req, State) ->
%% with Location the full new URI of the resource.
moved_permanently(Req, State, OnFalse) ->
case call(Req, State, moved_permanently) of
- {{true, Location}, Req2, HandlerState2} ->
+ {{true, Location}, Req2, HandlerState} ->
{ok, Req3} = cowboy_http_req:set_resp_header(
<<"Location">>, Location, Req2),
- respond(Req3, State#state{handler_state=HandlerState2}, 301);
- {false, Req2, HandlerState2} ->
- OnFalse(Req2, State#state{handler_state=HandlerState2});
+ respond(Req3, State#state{handler_state=HandlerState}, 301);
+ {false, Req2, HandlerState} ->
+ OnFalse(Req2, State#state{handler_state=HandlerState});
+ {halt, Req2, HandlerState} ->
+ terminate(Req2, State#state{handler_state=HandlerState});
no_call ->
OnFalse(Req, State)
end.
@@ -598,12 +617,14 @@ previously_existed(Req, State) ->
%% with Location the full new URI of the resource.
moved_temporarily(Req, State) ->
case call(Req, State, moved_temporarily) of
- {{true, Location}, Req2, HandlerState2} ->
+ {{true, Location}, Req2, HandlerState} ->
{ok, Req3} = cowboy_http_req:set_resp_header(
<<"Location">>, Location, Req2),
- respond(Req3, State#state{handler_state=HandlerState2}, 307);
- {false, Req2, HandlerState2} ->
- is_post_to_missing_resource(Req2, State#state{handler_state=HandlerState2}, 410);
+ respond(Req3, State#state{handler_state=HandlerState}, 307);
+ {false, Req2, HandlerState} ->
+ is_post_to_missing_resource(Req2, State#state{handler_state=HandlerState}, 410);
+ {halt, Req2, HandlerState} ->
+ terminate(Req2, State#state{handler_state=HandlerState});
no_call ->
is_post_to_missing_resource(Req, State, 410)
end.
@@ -642,6 +663,8 @@ post_is_create(Req, State) ->
%% (including the leading /).
create_path(Req=#http_req{meta=Meta}, State) ->
case call(Req, State, create_path) of
+ {halt, Req2, HandlerState} ->
+ terminate(Req2, State#state{handler_state=HandlerState});
{Path, Req2, HandlerState} ->
Location = create_path_location(Req2, Path),
State2 = State#state{handler_state=HandlerState},
@@ -672,6 +695,8 @@ create_path_location_port(_, Port) ->
%% and false when it hasn't, in which case a 500 error is sent.
process_post(Req, State) ->
case call(Req, State, process_post) of
+ {halt, Req2, HandlerState} ->
+ terminate(Req2, State#state{handler_state=HandlerState});
{true, Req2, HandlerState} ->
State2 = State#state{handler_state=HandlerState},
next(Req2, State2, 201);
@@ -699,8 +724,10 @@ put_resource(Req, State, OnTrue) ->
case call(Req, State, content_types_accepted) of
no_call ->
respond(Req, State, 415);
- {CTA, Req2, HandlerState2} ->
- State2 = State#state{handler_state=HandlerState2},
+ {halt, Req2, HandlerState} ->
+ terminate(Req2, State#state{handler_state=HandlerState});
+ {CTA, Req2, HandlerState} ->
+ State2 = State#state{handler_state=HandlerState},
{ContentType, Req3}
= cowboy_http_req:parse_header('Content-Type', Req2),
choose_content_type(Req3, State2, OnTrue, ContentType, CTA)
@@ -711,6 +738,8 @@ choose_content_type(Req, State, _OnTrue, _ContentType, []) ->
choose_content_type(Req, State, OnTrue, ContentType,
[{Accepted, Fun}|_Tail]) when ContentType =:= Accepted ->
case call(Req, State, Fun) of
+ {halt, Req2, HandlerState} ->
+ terminate(Req2, State#state{handler_state=HandlerState});
{true, Req2, HandlerState} ->
State2 = State#state{handler_state=HandlerState},
next(Req2, State2, OnTrue);
@@ -754,6 +783,8 @@ set_resp_body(Req=#http_req{method=Method},
end,
{Req5, State4} = set_resp_expires(Req4, State3),
case call(Req5, State4, Fun) of
+ {halt, Req6, HandlerState} ->
+ terminate(Req6, State4#state{handler_state=HandlerState});
{Body, Req6, HandlerState} ->
State5 = State4#state{handler_state=HandlerState},
{ok, Req7} = case Body of
@@ -803,8 +834,8 @@ generate_etag(Req, State=#state{etag=undefined}) ->
case call(Req, State, generate_etag) of
no_call ->
{undefined, Req, State#state{etag=no_call}};
- {Etag, Req2, HandlerState2} ->
- {Etag, Req2, State#state{handler_state=HandlerState2, etag=Etag}}
+ {Etag, Req2, HandlerState} ->
+ {Etag, Req2, State#state{handler_state=HandlerState, etag=Etag}}
end;
generate_etag(Req, State=#state{etag=Etag}) ->
{Etag, Req, State}.
@@ -815,8 +846,8 @@ last_modified(Req, State=#state{last_modified=undefined}) ->
case call(Req, State, last_modified) of
no_call ->
{undefined, Req, State#state{last_modified=no_call}};
- {LastModified, Req2, HandlerState2} ->
- {LastModified, Req2, State#state{handler_state=HandlerState2,
+ {LastModified, Req2, HandlerState} ->
+ {LastModified, Req2, State#state{handler_state=HandlerState,
last_modified=LastModified}}
end;
last_modified(Req, State=#state{last_modified=LastModified}) ->
@@ -828,8 +859,8 @@ expires(Req, State=#state{expires=undefined}) ->
case call(Req, State, expires) of
no_call ->
{undefined, Req, State#state{expires=no_call}};
- {Expires, Req2, HandlerState2} ->
- {Expires, Req2, State#state{handler_state=HandlerState2,
+ {Expires, Req2, HandlerState} ->
+ {Expires, Req2, State#state{handler_state=HandlerState,
expires=Expires}}
end;
expires(Req, State=#state{expires=Expires}) ->
@@ -841,10 +872,12 @@ expect(Req, State, Callback, Expected, OnTrue, OnFalse) ->
case call(Req, State, Callback) of
no_call ->
next(Req, State, OnTrue);
- {Expected, Req2, HandlerState2} ->
- next(Req2, State#state{handler_state=HandlerState2}, OnTrue);
- {_Unexpected, Req2, HandlerState2} ->
- next(Req2, State#state{handler_state=HandlerState2}, OnFalse)
+ {halt, Req2, HandlerState} ->
+ terminate(Req2, State#state{handler_state=HandlerState});
+ {Expected, Req2, HandlerState} ->
+ next(Req2, State#state{handler_state=HandlerState}, OnTrue);
+ {_Unexpected, Req2, HandlerState} ->
+ next(Req2, State#state{handler_state=HandlerState}, OnFalse)
end.
call(Req, #state{handler=Handler, handler_state=HandlerState}, Fun) ->