aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2018-11-04 11:51:35 +0100
committerLoïc Hoguin <[email protected]>2018-11-04 11:58:59 +0100
commit8c9ad7bf078871295e391f416bfcb10c9156a35f (patch)
treef92cf4f4ff6f978405cf8171e86b44de27f91265 /src
parentbf7ccc8623610d34cf3323db776b280a50275678 (diff)
downloadcowboy-8c9ad7bf078871295e391f416bfcb10c9156a35f.tar.gz
cowboy-8c9ad7bf078871295e391f416bfcb10c9156a35f.tar.bz2
cowboy-8c9ad7bf078871295e391f416bfcb10c9156a35f.zip
Add the rate_limited/2 REST callback
Diffstat (limited to 'src')
-rw-r--r--src/cowboy_rest.erl30
1 files changed, 29 insertions, 1 deletions
diff --git a/src/cowboy_rest.erl b/src/cowboy_rest.erl
index 512dc5b..8ab576c 100644
--- a/src/cowboy_rest.erl
+++ b/src/cowboy_rest.erl
@@ -180,6 +180,13 @@
when Req::cowboy_req:req(), State::any().
-optional_callbacks([previously_existed/2]).
+-callback rate_limited(Req, State)
+ -> {{true, non_neg_integer() | calendar:datetime()} | false, Req, State}
+ | {stop, Req, State}
+ | {switch_handler(), Req, State}
+ when Req::cowboy_req:req(), State::any().
+-optional_callbacks([rate_limited/2]).
+
-callback resource_exists(Req, State)
-> {boolean(), Req, State}
| {stop, Req, State}
@@ -363,7 +370,28 @@ is_authorized(Req, State) ->
end.
forbidden(Req, State) ->
- expect(Req, State, forbidden, false, fun valid_content_headers/2, 403).
+ expect(Req, State, forbidden, false, fun rate_limited/2, 403).
+
+rate_limited(Req, State) ->
+ case call(Req, State, rate_limited) of
+ no_call ->
+ valid_content_headers(Req, State);
+ {stop, Req2, HandlerState} ->
+ terminate(Req2, State#state{handler_state=HandlerState});
+ {Switch, Req2, HandlerState} when element(1, Switch) =:= switch_handler ->
+ switch_handler(Switch, Req2, HandlerState);
+ {false, Req2, HandlerState} ->
+ valid_content_headers(Req2, State#state{handler_state=HandlerState});
+ {{true, RetryAfter0}, Req2, HandlerState} ->
+ RetryAfter = if
+ is_integer(RetryAfter0), RetryAfter0 >= 0 ->
+ integer_to_binary(RetryAfter0);
+ is_tuple(RetryAfter0) ->
+ cowboy_clock:rfc1123(RetryAfter0)
+ end,
+ Req3 = cowboy_req:set_resp_header(<<"retry-after">>, RetryAfter, Req2),
+ respond(Req3, State#state{handler_state=HandlerState}, 429)
+ end.
valid_content_headers(Req, State) ->
expect(Req, State, valid_content_headers, true,