diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cowboy.app.src | 2 | ||||
-rw-r--r-- | src/cowboy_protocol.erl | 14 | ||||
-rw-r--r-- | src/cowboy_req.erl | 130 | ||||
-rw-r--r-- | src/cowboy_rest.erl | 120 | ||||
-rw-r--r-- | src/cowboy_static.erl | 3 | ||||
-rw-r--r-- | src/cowboy_websocket.erl | 4 |
6 files changed, 89 insertions, 184 deletions
diff --git a/src/cowboy.app.src b/src/cowboy.app.src index f4dcac2..d224c5d 100644 --- a/src/cowboy.app.src +++ b/src/cowboy.app.src @@ -17,7 +17,7 @@ {description, "Small, fast, modular HTTP server."}, {sub_description, "Cowboy is also a socket acceptor pool, " "able to accept connections for any kind of TCP protocol."}, - {vsn, "0.8.2"}, + {vsn, "0.8.3"}, {modules, []}, {registered, [cowboy_clock, cowboy_sup]}, {applications, [ diff --git a/src/cowboy_protocol.erl b/src/cowboy_protocol.erl index 78e3b78..be351b7 100644 --- a/src/cowboy_protocol.erl +++ b/src/cowboy_protocol.erl @@ -84,9 +84,9 @@ %% API. %% @doc Start an HTTP protocol process. --spec start_link(pid(), inet:socket(), module(), any()) -> {ok, pid()}. -start_link(ListenerPid, Socket, Transport, Opts) -> - Pid = spawn_link(?MODULE, init, [ListenerPid, Socket, Transport, Opts]), +-spec start_link(any(), inet:socket(), module(), any()) -> {ok, pid()}. +start_link(Ref, Socket, Transport, Opts) -> + Pid = spawn_link(?MODULE, init, [Ref, Socket, Transport, Opts]), {ok, Pid}. %% Internal. @@ -100,8 +100,8 @@ get_value(Key, Opts, Default) -> end. %% @private --spec init(pid(), inet:socket(), module(), any()) -> ok. -init(ListenerPid, Socket, Transport, Opts) -> +-spec init(any(), inet:socket(), module(), any()) -> ok. +init(Ref, Socket, Transport, Opts) -> Compress = get_value(compress, Opts, false), MaxEmptyLines = get_value(max_empty_lines, Opts, 5), MaxHeaderNameLength = get_value(max_header_name_length, Opts, 64), @@ -110,11 +110,11 @@ init(ListenerPid, Socket, Transport, Opts) -> MaxKeepalive = get_value(max_keepalive, Opts, 100), MaxRequestLineLength = get_value(max_request_line_length, Opts, 4096), Middlewares = get_value(middlewares, Opts, [cowboy_router, cowboy_handler]), - Env = [{listener, ListenerPid}|get_value(env, Opts, [])], + Env = [{listener, Ref}|get_value(env, Opts, [])], OnRequest = get_value(onrequest, Opts, undefined), OnResponse = get_value(onresponse, Opts, undefined), Timeout = get_value(timeout, Opts, 5000), - ok = ranch:accept_ack(ListenerPid), + ok = ranch:accept_ack(Ref), wait_request(<<>>, #state{socket=Socket, transport=Transport, middlewares=Middlewares, compress=Compress, env=Env, max_empty_lines=MaxEmptyLines, max_keepalive=MaxKeepalive, diff --git a/src/cowboy_req.erl b/src/cowboy_req.erl index 966e463..4ec42f9 100644 --- a/src/cowboy_req.erl +++ b/src/cowboy_req.erl @@ -46,7 +46,6 @@ -export([method/1]). -export([version/1]). -export([peer/1]). --export([peer_addr/1]). -export([host/1]). -export([host_info/1]). -export([port/1]). @@ -78,8 +77,8 @@ -export([has_body/1]). -export([body_length/1]). -export([init_stream/4]). --export([init_stream/5]). -export([stream_body/1]). +-export([stream_body/2]). -export([skip_body/1]). -export([body/1]). -export([body/2]). @@ -155,8 +154,8 @@ meta = [] :: [{atom(), any()}], %% Request body. - body_state = waiting :: waiting | done | {stream, - non_neg_integer(), non_neg_integer(), fun(), any(), fun()}, + body_state = waiting :: waiting | done + | {stream, non_neg_integer(), fun(), any(), fun()}, multipart = undefined :: undefined | {non_neg_integer(), fun()}, buffer = <<>> :: binary(), @@ -230,29 +229,6 @@ version(Req) -> peer(Req) -> {Req#http_req.peer, Req}. -%% @doc Returns the peer address calculated from headers. --spec peer_addr(Req) -> {inet:ip_address(), Req} when Req::req(). -peer_addr(Req = #http_req{}) -> - {RealIp, Req1} = header(<<"x-real-ip">>, Req), - {ForwardedForRaw, Req2} = header(<<"x-forwarded-for">>, Req1), - {{PeerIp, _PeerPort}, Req3} = peer(Req2), - ForwardedFor = case ForwardedForRaw of - undefined -> - undefined; - ForwardedForRaw -> - case re:run(ForwardedForRaw, "^(?<first_ip>[^\\,]+)", - [{capture, [first_ip], binary}]) of - {match, [FirstIp]} -> FirstIp; - _Any -> undefined - end - end, - {ok, PeerAddr} = if - is_binary(RealIp) -> inet_parse:address(binary_to_list(RealIp)); - is_binary(ForwardedFor) -> inet_parse:address(binary_to_list(ForwardedFor)); - true -> {ok, PeerIp} - end, - {PeerAddr, Req3}. - %% @doc Return the host binary string. -spec host(Req) -> {binary(), Req} when Req::req(). host(Req) -> @@ -426,61 +402,61 @@ parse_header_default(_Name) -> undefined. -spec parse_header(binary(), Req, any()) -> {ok, any(), Req} | {undefined, binary(), Req} | {error, badarg} when Req::req(). -parse_header(Name, Req, Default) when Name =:= <<"accept">> -> +parse_header(Name = <<"accept">>, Req, Default) -> parse_header(Name, Req, Default, fun (Value) -> cowboy_http:list(Value, fun cowboy_http:media_range/2) end); -parse_header(Name, Req, Default) when Name =:= <<"accept-charset">> -> +parse_header(Name = <<"accept-charset">>, Req, Default) -> parse_header(Name, Req, Default, fun (Value) -> cowboy_http:nonempty_list(Value, fun cowboy_http:conneg/2) end); -parse_header(Name, Req, Default) when Name =:= <<"accept-encoding">> -> +parse_header(Name = <<"accept-encoding">>, Req, Default) -> parse_header(Name, Req, Default, fun (Value) -> cowboy_http:list(Value, fun cowboy_http:conneg/2) end); -parse_header(Name, Req, Default) when Name =:= <<"accept-language">> -> +parse_header(Name = <<"accept-language">>, Req, Default) -> parse_header(Name, Req, Default, fun (Value) -> cowboy_http:nonempty_list(Value, fun cowboy_http:language_range/2) end); -parse_header(Name, Req, Default) when Name =:= <<"authorization">> -> +parse_header(Name = <<"authorization">>, Req, Default) -> parse_header(Name, Req, Default, fun (Value) -> cowboy_http:token_ci(Value, fun cowboy_http:authorization/2) end); -parse_header(Name, Req, Default) when Name =:= <<"content-length">> -> +parse_header(Name = <<"content-length">>, Req, Default) -> parse_header(Name, Req, Default, fun cowboy_http:digits/1); -parse_header(Name, Req, Default) when Name =:= <<"content-type">> -> +parse_header(Name = <<"content-type">>, Req, Default) -> parse_header(Name, Req, Default, fun cowboy_http:content_type/1); parse_header(Name = <<"cookie">>, Req, Default) -> parse_header(Name, Req, Default, fun cowboy_http:cookie_list/1); -parse_header(Name, Req, Default) when Name =:= <<"expect">> -> +parse_header(Name = <<"expect">>, Req, Default) -> parse_header(Name, Req, Default, fun (Value) -> cowboy_http:nonempty_list(Value, fun cowboy_http:expectation/2) end); parse_header(Name, Req, Default) - when Name =:= <<"if-match">>; Name =:= <<"if-none-match">> -> + when Name =:= <<"if-match">>; + Name =:= <<"if-none-match">> -> parse_header(Name, Req, Default, fun cowboy_http:entity_tag_match/1); parse_header(Name, Req, Default) when Name =:= <<"if-modified-since">>; Name =:= <<"if-unmodified-since">> -> parse_header(Name, Req, Default, fun cowboy_http:http_date/1); -parse_header(Name, Req, Default) when Name =:= <<"sec-websocket-protocol">> -> +parse_header(Name, Req, Default) + when Name =:= <<"sec-websocket-protocol">>; + Name =:= <<"x-forwarded-for">> -> parse_header(Name, Req, Default, fun (Value) -> cowboy_http:nonempty_list(Value, fun cowboy_http:token/2) end); %% @todo Extension parameters. -parse_header(Name, Req, Default) when Name =:= <<"transfer-encoding">> -> - parse_header(Name, Req, Default, - fun (Value) -> - cowboy_http:nonempty_list(Value, fun cowboy_http:token_ci/2) - end); -parse_header(Name, Req, Default) when Name =:= <<"upgrade">> -> +parse_header(Name, Req, Default) + when Name =:= <<"transfer-encoding">>; + Name =:= <<"upgrade">> -> parse_header(Name, Req, Default, fun (Value) -> cowboy_http:nonempty_list(Value, fun cowboy_http:token_ci/2) @@ -566,7 +542,7 @@ set_meta(Name, Value, Req=#http_req{meta=Meta}) -> %% Request Body API. %% @doc Return whether the request message has a body. --spec has_body(cowboy_req:req()) -> boolean(). +-spec has_body(req()) -> boolean(). has_body(Req) -> case lists:keyfind(<<"content-length">>, 1, Req#http_req.headers) of {_, <<"0">>} -> @@ -591,17 +567,11 @@ body_length(Req) -> {undefined, Req2} end. -%% @equiv init_stream(1000000, TransferDecode, TransferState, ContentDecode, Req) --spec init_stream(fun(), any(), fun(), Req) - -> {ok, Req} when Req::req(). -init_stream(TransferDecode, TransferState, ContentDecode, Req) -> - init_stream(1000000, TransferDecode, TransferState, ContentDecode, Req). - %% @doc Initialize body streaming and set custom decoding functions. %% %% Calling this function is optional. It should only be used if you %% need to override the default behavior of Cowboy. Otherwise you -%% should call stream_body/1 directly. +%% should call stream_body/{1,2} directly. %% %% Two decodings happen. First a decoding function is applied to the %% transferred data, and then another is applied to the actual content. @@ -613,27 +583,36 @@ init_stream(TransferDecode, TransferState, ContentDecode, Req) -> %% Content encoding is generally used for compression. %% %% Standard encodings can be found in cowboy_http. --spec init_stream(non_neg_integer(), fun(), any(), fun(), Req) +-spec init_stream(fun(), any(), fun(), Req) -> {ok, Req} when Req::req(). -init_stream(MaxLength, TransferDecode, TransferState, ContentDecode, Req) -> +init_stream(TransferDecode, TransferState, ContentDecode, Req) -> {ok, Req#http_req{body_state= - {stream, 0, MaxLength, TransferDecode, TransferState, ContentDecode}}}. + {stream, 0, TransferDecode, TransferState, ContentDecode}}}. + +%% @equiv stream_body(1000000, Req) +-spec stream_body(Req) -> {ok, binary(), Req} + | {done, Req} | {error, atom()} when Req::req(). +stream_body(Req) -> + stream_body(1000000, Req). %% @doc Stream the request's body. %% %% This is the most low level function to read the request body. %% -%% In most cases, if they weren't defined before using stream_body/4, +%% In most cases, if they weren't defined before using init_stream/4, %% this function will guess which transfer and content encodings were %% used for building the request body, and configure the decoding %% functions that will be used when streaming. %% %% It then starts streaming the body, returning {ok, Data, Req} %% for each streamed part, and {done, Req} when it's finished streaming. --spec stream_body(Req) -> {ok, binary(), Req} +%% +%% You can limit the size of the chunks being returned by using the +%% second argument which is the size in bytes. It defaults to 1000000 bytes. +-spec stream_body(non_neg_integer(), Req) -> {ok, binary(), Req} | {done, Req} | {error, atom()} when Req::req(). -stream_body(Req=#http_req{body_state=waiting, - version=Version, transport=Transport, socket=Socket}) -> +stream_body(MaxLength, Req=#http_req{body_state=waiting, version=Version, + transport=Transport, socket=Socket}) -> {ok, ExpectHeader, Req1} = parse_header(<<"expect">>, Req), case ExpectHeader of [<<"100-continue">>] -> @@ -645,8 +624,8 @@ stream_body(Req=#http_req{body_state=waiting, end, case parse_header(<<"transfer-encoding">>, Req1) of {ok, [<<"chunked">>], Req2} -> - stream_body(Req2#http_req{body_state= - {stream, 0, 1000000, + stream_body(MaxLength, Req2#http_req{body_state= + {stream, 0, fun cowboy_http:te_chunked/2, {0, 0}, fun cowboy_http:ce_identity/1}}); {ok, [<<"identity">>], Req2} -> @@ -655,25 +634,25 @@ stream_body(Req=#http_req{body_state=waiting, 0 -> {done, Req3#http_req{body_state=done}}; Length -> - stream_body(Req3#http_req{body_state= - {stream, Length, 1000000, + stream_body(MaxLength, Req3#http_req{body_state= + {stream, Length, fun cowboy_http:te_identity/2, {0, Length}, fun cowboy_http:ce_identity/1}}) end end; -stream_body(Req=#http_req{body_state=done}) -> +stream_body(_, Req=#http_req{body_state=done}) -> {done, Req}; -stream_body(Req=#http_req{buffer=Buffer}) +stream_body(_, Req=#http_req{buffer=Buffer}) when Buffer =/= <<>> -> transfer_decode(Buffer, Req#http_req{buffer= <<>>}); -stream_body(Req) -> - stream_body_recv(Req). +stream_body(MaxLength, Req) -> + stream_body_recv(MaxLength, Req). --spec stream_body_recv(Req) +-spec stream_body_recv(non_neg_integer(), Req) -> {ok, binary(), Req} | {error, atom()} when Req::req(). -stream_body_recv(Req=#http_req{ +stream_body_recv(MaxLength, Req=#http_req{ transport=Transport, socket=Socket, buffer=Buffer, - body_state={stream, Length, MaxLength, _, _, _}}) -> + body_state={stream, Length, _, _, _}}) -> %% @todo Allow configuring the timeout. case Transport:recv(Socket, min(Length, MaxLength), 5000) of {ok, Data} -> transfer_decode(<< Buffer/binary, Data/binary >>, @@ -683,20 +662,20 @@ stream_body_recv(Req=#http_req{ -spec transfer_decode(binary(), Req) -> {ok, binary(), Req} | {error, atom()} when Req::req(). -transfer_decode(Data, Req=#http_req{body_state={stream, _, MaxLength, +transfer_decode(Data, Req=#http_req{body_state={stream, _, TransferDecode, TransferState, ContentDecode}}) -> case TransferDecode(Data, TransferState) of {ok, Data2, Rest, TransferState2} -> content_decode(ContentDecode, Data2, - Req#http_req{buffer=Rest, body_state={stream, 0, MaxLength, + Req#http_req{buffer=Rest, body_state={stream, 0, TransferDecode, TransferState2, ContentDecode}}); %% @todo {header(s) for chunked more -> - stream_body_recv(Req#http_req{buffer=Data, body_state={stream, - 0, MaxLength, TransferDecode, TransferState, ContentDecode}}); + stream_body_recv(0, Req#http_req{buffer=Data, body_state={stream, + 0, TransferDecode, TransferState, ContentDecode}}); {more, Length, Data2, TransferState2} -> content_decode(ContentDecode, Data2, - Req#http_req{body_state={stream, Length, MaxLength, + Req#http_req{body_state={stream, Length, TransferDecode, TransferState2, ContentDecode}}); {done, Length, Rest} -> Req2 = transfer_decode_done(Length, Rest, Req), @@ -1010,8 +989,7 @@ reply(Status, Headers, Body, Req=#http_req{ reply_may_compress(Status, Headers, Body, Req, RespHeaders, HTTP11Headers, Method) -> BodySize = iolist_size(Body), - {ok, Encodings, Req2} - = cowboy_req:parse_header(<<"accept-encoding">>, Req), + {ok, Encodings, Req2} = parse_header(<<"accept-encoding">>, Req), CanGzip = (BodySize > 300) andalso (false =:= lists:keyfind(<<"content-encoding">>, 1, Headers)) diff --git a/src/cowboy_rest.erl b/src/cowboy_rest.erl index cb4fffb..526f102 100644 --- a/src/cowboy_rest.erl +++ b/src/cowboy_rest.erl @@ -96,9 +96,8 @@ known_methods(Req, State=#state{method=Method}) -> case call(Req, State, known_methods) of no_call when Method =:= <<"HEAD">>; Method =:= <<"GET">>; Method =:= <<"POST">>; Method =:= <<"PUT">>; - Method =:= <<"DELETE">>; Method =:= <<"TRACE">>; - Method =:= <<"CONNECT">>; Method =:= <<"OPTIONS">>; - Method =:= <<"PATCH">> -> + Method =:= <<"PATCH">>; Method =:= <<"DELETE">>; + Method =:= <<"OPTIONS">> -> next(Req, State, fun uri_too_long/2); no_call -> next(Req, State, 501); @@ -236,8 +235,8 @@ content_types_provided(Req, State) -> normalize_content_types({ContentType, Callback}) when is_binary(ContentType) -> {cowboy_http:content_type(ContentType), Callback}; -normalize_content_types(Provided) -> - Provided. +normalize_content_types(Normalized) -> + Normalized. prioritize_accept(Accept) -> lists:sort( @@ -728,16 +727,18 @@ is_post_to_missing_resource(Req, State, OnFalse) -> respond(Req, State, OnFalse). allow_missing_post(Req, State, OnFalse) -> - expect(Req, State, allow_missing_post, true, fun post_is_create/2, OnFalse). + expect(Req, State, allow_missing_post, true, fun post_resource/2, OnFalse). + +post_resource(Req, State) -> + accept_resource(Req, State, 204). method(Req, State=#state{method= <<"DELETE">>}) -> delete_resource(Req, State); -method(Req, State=#state{method= <<"POST">>}) -> - post_is_create(Req, State); method(Req, State=#state{method= <<"PUT">>}) -> is_conflict(Req, State); -method(Req, State=#state{method= <<"PATCH">>}) -> - patch_resource(Req, State); +method(Req, State=#state{method=Method}) + when Method =:= <<"POST">>; Method =:= <<"PATCH">> -> + accept_resource(Req, State, 204); method(Req, State=#state{method=Method}) when Method =:= <<"GET">>; Method =:= <<"HEAD">> -> set_resp_body_etag(Req, State); @@ -752,79 +753,21 @@ delete_resource(Req, State) -> delete_completed(Req, State) -> expect(Req, State, delete_completed, true, fun has_resp_body/2, 202). -%% post_is_create/2 indicates whether the POST method can create new resources. -post_is_create(Req, State) -> - expect(Req, State, post_is_create, false, fun process_post/2, fun create_path/2). - -%% When the POST method can create new resources, create_path/2 will be called -%% and is expected to return the full path to the new resource -%% (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} -> - {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), - put_resource(cowboy_req:set_meta(put_path, Path, Req4), - 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) -> - 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, fun is_new_resource/2); - {false, Req2, HandlerState} -> - State2 = State#state{handler_state=HandlerState}, - respond(Req2, State2, 500) - end. - is_conflict(Req, State) -> expect(Req, State, is_conflict, false, fun put_resource/2, 409). put_resource(Req, State) -> - Path = cowboy_req:get(path, Req), - put_resource(cowboy_req:set_meta(put_path, Path, Req), - State, fun is_new_resource/2). + accept_resource(Req, State, fun is_new_resource/2). %% content_types_accepted should return a list of media types and their %% associated callback functions in the same format as content_types_provided. %% %% The callback will then be called and is expected to process the content -%% pushed to the resource in the request body. The path to the new resource -%% may be different from the request path, and is stored as request metadata. -%% It is always defined past this point. It can be retrieved as demonstrated: -%% {PutPath, Req2} = cowboy_req:meta(put_path, Req) +%% pushed to the resource in the request body. %% -%%content_types_accepted SHOULD return a different list +%% content_types_accepted SHOULD return a different list %% for each HTTP method. -put_resource(Req, State, OnTrue) -> +accept_resource(Req, State, OnTrue) -> case call(Req, State, content_types_accepted) of no_call -> respond(Req, State, 415); @@ -838,27 +781,6 @@ put_resource(Req, State, OnTrue) -> choose_content_type(Req3, State2, OnTrue, ContentType, CTA2) end. -%% content_types_accepted should return a list of media types and their -%% associated callback functions in the same format as content_types_provided. -%% -%% The callback will then be called and is expected to process the content -%% pushed to the resource in the request body. -%% -%% content_types_accepted SHOULD return a different list -%% for each HTTP method. -patch_resource(Req, State) -> - case call(Req, State, content_types_accepted) of - no_call -> - respond(Req, State, 415); - {halt, Req2, HandlerState} -> - terminate(Req2, State#state{handler_state=HandlerState}); - {CTM, Req2, HandlerState} -> - State2 = State#state{handler_state=HandlerState}, - {ok, ContentType, Req3} - = cowboy_req:parse_header(<<"content-type">>, Req2), - choose_content_type(Req3, State2, 204, ContentType, CTM) - end. - %% The special content type '*' will always match. It can be used as a %% catch-all content type for accepting any kind of request content. %% Note that because it will always match, it should be the last of the @@ -880,9 +802,8 @@ choose_content_type(Req, State, OnTrue, choose_content_type(Req, State, OnTrue, ContentType, [_Any|Tail]) -> choose_content_type(Req, State, OnTrue, ContentType, Tail). -process_content_type(Req, - State=#state{handler=Handler, handler_state=HandlerState}, - OnTrue, Fun) -> +process_content_type(Req, State=#state{method=Method, + handler=Handler, handler_state=HandlerState}, OnTrue, Fun) -> case call(Req, State, Fun) of no_call -> error_logger:error_msg( @@ -898,7 +819,12 @@ process_content_type(Req, next(Req2, State2, OnTrue); {false, Req2, HandlerState2} -> State2 = State#state{handler_state=HandlerState2}, - respond(Req2, State2, 422) + respond(Req2, State2, 422); + {ResURL, Req2, HandlerState2} when Method =:= <<"POST">> -> + State2 = State#state{handler_state=HandlerState2}, + Req3 = cowboy_req:set_resp_header( + <<"location">>, ResURL, Req2), + respond(Req3, State2, 303) end. %% Whether we created a new resource, either through PUT or POST. diff --git a/src/cowboy_static.erl b/src/cowboy_static.erl index d583fa9..fe6600c 100644 --- a/src/cowboy_static.erl +++ b/src/cowboy_static.erl @@ -324,7 +324,8 @@ file_contents(Req, #state{filepath=Filepath, %% if the connection is closed while sending the file. case Transport:sendfile(Socket, Filepath) of {ok, _} -> ok; - {error, closed} -> ok + {error, closed} -> ok; + {error, etimedout} -> ok end end, {{stream, Filesize, Writefile}, Req, State}. diff --git a/src/cowboy_websocket.erl b/src/cowboy_websocket.erl index 7bb5e74..b5075c0 100644 --- a/src/cowboy_websocket.erl +++ b/src/cowboy_websocket.erl @@ -63,8 +63,8 @@ | {suspend, module(), atom(), [any()]} when Req::cowboy_req:req(), Env::cowboy_middleware:env(). upgrade(Req, Env, Handler, HandlerOpts) -> - {_, ListenerPid} = lists:keyfind(listener, 1, Env), - ranch_listener:remove_connection(ListenerPid), + {_, Ref} = lists:keyfind(listener, 1, Env), + ranch:remove_connection(Ref), [Socket, Transport] = cowboy_req:get([socket, transport], Req), State = #state{env=Env, socket=Socket, transport=Transport, handler=Handler, handler_opts=HandlerOpts}, |