aboutsummaryrefslogtreecommitdiffstats
path: root/src/cowboy_stream.erl
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2017-03-27 10:26:13 +0200
committerLoïc Hoguin <[email protected]>2017-03-27 10:26:13 +0200
commit10dfd8c910bce3ae71146f8f13eef25b34ec093a (patch)
treee491e7602e69c5eb82dc7ea5b25c269f0c4cd4d2 /src/cowboy_stream.erl
parent14a01f71cb495ef6be5e31122857d1e4438cecfe (diff)
downloadcowboy-10dfd8c910bce3ae71146f8f13eef25b34ec093a.tar.gz
cowboy-10dfd8c910bce3ae71146f8f13eef25b34ec093a.tar.bz2
cowboy-10dfd8c910bce3ae71146f8f13eef25b34ec093a.zip
Add the early_error cowboy_stream callback
This callback is called when an error occurs before the request (including headers, excluding body) was fully received. The init/3 callback will not be called. The callback receives the partial Req object (possibly empty), the reason for the error and the response command that the server will send. It allows you to be aware of the error and possibly modify the response before it is sent.
Diffstat (limited to 'src/cowboy_stream.erl')
-rw-r--r--src/cowboy_stream.erl24
1 files changed, 23 insertions, 1 deletions
diff --git a/src/cowboy_stream.erl b/src/cowboy_stream.erl
index 19b3663..d4ddc9f 100644
--- a/src/cowboy_stream.erl
+++ b/src/cowboy_stream.erl
@@ -25,7 +25,11 @@
%% @todo Perhaps it makes more sense to have resp_body in this module?
--type commands() :: [{response, cowboy:http_status(), cowboy:http_headers(), cowboy_req:resp_body()}
+-type resp_command()
+ :: {response, cowboy:http_status(), cowboy:http_headers(), cowboy_req:resp_body()}.
+-export_type([resp_command/0]).
+
+-type commands() :: [resp_command()
| {headers, cowboy:http_status(), cowboy:http_headers()}
| {data, fin(), iodata()}
| {push, binary(), binary(), binary(), inet:port_number(),
@@ -51,10 +55,15 @@
| {stop, cow_http2:frame(), human_reason()}.
-export_type([reason/0]).
+-type partial_req() :: map(). %% @todo Take what's in cowboy_req with everything? optional.
+-export_type([partial_req/0]).
+
-callback init(streamid(), cowboy_req:req(), cowboy:opts()) -> {commands(), state()}.
-callback data(streamid(), fin(), binary(), State) -> {commands(), State} when State::state().
-callback info(streamid(), any(), State) -> {commands(), State} when State::state().
-callback terminate(streamid(), reason(), state()) -> any().
+-callback early_error(streamid(), reason(), partial_req(), Resp, cowboy:opts())
+ -> Resp when Resp::resp_command().
%% @todo To optimize the number of active timers we could have a command
%% that enables a timeout that is called in the absence of any other call,
@@ -71,6 +80,7 @@
-export([data/4]).
-export([info/3]).
-export([terminate/3]).
+-export([early_error/5]).
%% Note that this and other functions in this module do NOT catch
%% exceptions. We want the exception to go all the way down to the
@@ -127,3 +137,15 @@ terminate(_, _, undefined) ->
terminate(StreamID, Reason, {Handler, State}) ->
_ = Handler:terminate(StreamID, Reason, State),
ok.
+
+-spec early_error(streamid(), reason(), partial_req(), Resp, cowboy:opts())
+ -> Resp when Resp::resp_command().
+early_error(StreamID, Reason, PartialReq, Resp, Opts) ->
+ case maps:get(stream_handlers, Opts, [cowboy_stream_h]) of
+ [] ->
+ Resp;
+ [Handler|Tail] ->
+ %% This is the same behavior as in init/3.
+ Handler:early_error(StreamID, Reason,
+ PartialReq, Resp, Opts#{stream_handlers => Tail})
+ end.