diff options
-rw-r--r-- | src/cowboy_http.erl | 14 | ||||
-rw-r--r-- | src/cowboy_http2.erl | 11 | ||||
-rw-r--r-- | src/cowboy_loop.erl | 6 | ||||
-rw-r--r-- | src/cowboy_rest.erl | 13 |
4 files changed, 22 insertions, 22 deletions
diff --git a/src/cowboy_http.erl b/src/cowboy_http.erl index f38db97..d6436b2 100644 --- a/src/cowboy_http.erl +++ b/src/cowboy_http.erl @@ -106,7 +106,7 @@ out_streamid = 1 :: pos_integer(), %% Whether we finished writing data for the current stream. - out_state = wait :: wait | headers | chunked, + out_state = wait :: wait | headers | chunked | done, %% The connection will be closed after this stream. last_streamid = undefined :: pos_integer(), @@ -222,6 +222,7 @@ cancel_request_timeout(State=#state{timer=TimerRef}) -> end, State#state{timer=undefined}. +-spec timeout(_, _) -> no_return(). %% @todo Honestly it would be much better if we didn't enable pipelining yet. timeout(State=#state{in_state=#ps_request_line{}}, request_timeout) -> %% @todo If other streams are running, just set the connection to be closed @@ -302,7 +303,11 @@ after_parse({more, State, Buffer}) -> %% Request-line. --spec parse_request(binary(), #state{}, non_neg_integer()) -> ok. +-spec parse_request(Buffer, State, non_neg_integer()) + -> {request, cowboy_req:req(), State, Buffer} + | {data, cowboy_stream:streamid(), cowboy_stream:fin(), binary(), State, Buffer} + | {more, State, Buffer} + when Buffer::binary(), State::#state{}. %% Empty lines must be using \r\n. parse_request(<< $\n, _/bits >>, State, _) -> error_terminate(400, State, {connection_error, protocol_error, @@ -446,11 +451,12 @@ parse_header(<< $\r, $\n, Rest/bits >>, S, Headers) -> parse_header(Buffer, State=#state{opts=Opts, in_state=PS}, Headers) -> MaxLength = maps:get(max_header_name_length, Opts, 64), MaxHeaders = maps:get(max_headers, Opts, 100), + NumHeaders = maps:size(Headers), case match_colon(Buffer, 0) of nomatch when byte_size(Buffer) > MaxLength -> error_terminate(400, State, {connection_error, limit_reached, ''}); %% @todo - nomatch when length(Headers) >= MaxHeaders -> + nomatch when NumHeaders >= MaxHeaders -> error_terminate(400, State, {connection_error, limit_reached, ''}); %% @todo nomatch -> @@ -1016,12 +1022,14 @@ connection_hd_is_close(Conn) -> Conns = cow_http_hd:parse_connection(iolist_to_binary(Conn)), lists:member(<<"close">>, Conns). +-spec error_terminate(cowboy:http_status(), #state{}, _) -> no_return(). error_terminate(StatusCode, State=#state{socket=Socket, transport=Transport}, Reason) -> Transport:send(Socket, cow_http:response(StatusCode, 'HTTP/1.1', [ {<<"content-length">>, <<"0">>} ])), terminate(State, Reason). +-spec terminate(_, _) -> no_return(). terminate(_State, _Reason) -> exit(normal). %% @todo diff --git a/src/cowboy_http2.erl b/src/cowboy_http2.erl index 5c71628..ec19f4e 100644 --- a/src/cowboy_http2.erl +++ b/src/cowboy_http2.erl @@ -113,7 +113,7 @@ init(Parent, Ref, Socket, Transport, Opts, Handler, Peer, Buffer) -> %% @todo Add an argument for the request body. -spec init(pid(), ranch:ref(), inet:socket(), module(), cowboy:opts(), module(), - {inet:ip_address(), inet:port_number()}, binary(), binary() | undefined, cowboy_req:req()) -> ok. + {inet:ip_address(), inet:port_number()}, binary(), map() | undefined, cowboy_req:req()) -> ok. init(Parent, Ref, Socket, Transport, Opts, Handler, Peer, Buffer, _Settings, Req) -> State0 = #state{parent=Parent, ref=Ref, socket=Socket, transport=Transport, opts=Opts, handler=Handler, peer=Peer, @@ -235,7 +235,7 @@ parse(State=#state{parse_state=ParseState}, Data) -> end. parse_settings_preface(State, Frame={settings, _}, Rest, TRef) -> - erlang:cancel_timer(TRef, [{async, true}, {info, false}]), + _ = erlang:cancel_timer(TRef, [{async, true}, {info, false}]), parse(frame(State#state{parse_state=normal}, Frame), Rest); parse_settings_preface(State, _, _, _) -> terminate(State, {connection_error, protocol_error, @@ -330,11 +330,11 @@ frame(State, {continuation, _, _, _}) -> 'CONTINUATION frames MUST be preceded by a HEADERS frame. (RFC7540 6.10)'}). continuation_frame(State=#state{parse_state={continuation, StreamID, IsFin, HeaderBlockFragment0}}, - {continuation, StreamID, fin, HeaderBlockFragment1}) -> + {continuation, StreamID, head_fin, HeaderBlockFragment1}) -> stream_init(State#state{parse_state=normal}, StreamID, IsFin, << HeaderBlockFragment0/binary, HeaderBlockFragment1/binary >>); continuation_frame(State=#state{parse_state={continuation, StreamID, IsFin, HeaderBlockFragment0}}, - {continuation, StreamID, nofin, HeaderBlockFragment1}) -> + {continuation, StreamID, head_nofin, HeaderBlockFragment1}) -> State#state{parse_state={continuation, StreamID, IsFin, << HeaderBlockFragment0/binary, HeaderBlockFragment1/binary >>}}; continuation_frame(State, _) -> @@ -517,6 +517,7 @@ send_data(Socket, Transport, StreamID, IsFin, Data, Length) -> Transport:send(Socket, cow_http2:data(StreamID, IsFin, Data)) end. +-spec terminate(#state{}, _) -> no_return(). terminate(#state{socket=Socket, transport=Transport, handler=Handler, streams=Streams, children=Children}, Reason) -> %% @todo Send GOAWAY frame; need to keep track of last good stream id; how? @@ -686,7 +687,7 @@ headers_encode(Headers0, EncodeState) -> %% System callbacks. --spec system_continue(_, _, #state{}) -> ok. +-spec system_continue(_, _, {#state{}, binary()}) -> ok. system_continue(_, _, {State, Buffer}) -> loop(State, Buffer). diff --git a/src/cowboy_loop.erl b/src/cowboy_loop.erl index 8acf896..10f51ad 100644 --- a/src/cowboy_loop.erl +++ b/src/cowboy_loop.erl @@ -87,8 +87,8 @@ timeout(State=#state{timeout=infinity}) -> timeout(State=#state{timeout=Timeout, timeout_ref=PrevRef}) -> _ = case PrevRef of - undefined -> ignore; - PrevRef -> erlang:cancel_timer(PrevRef) + undefined -> ignore%; +% @todo PrevRef -> erlang:cancel_timer(PrevRef) end, TRef = erlang:start_timer(Timeout, self(), ?MODULE), State#state{timeout_ref=TRef}. @@ -127,7 +127,7 @@ terminate(Req, #state{env=Env, timeout_ref=TRef}, end, flush_timeouts(), Result = cowboy_handler:terminate(Reason, Req, HandlerState, Handler), - {ok, Req, [{result, Result}|Env]}. + {ok, Req, Env#{result => Result}}. flush_timeouts() -> receive diff --git a/src/cowboy_rest.erl b/src/cowboy_rest.erl index 3f6e55b..a3b764f 100644 --- a/src/cowboy_rest.erl +++ b/src/cowboy_rest.erl @@ -238,7 +238,7 @@ upgrade(Req0, Env, Handler, HandlerState, infinity, run) -> Method = cowboy_req:method(Req0), {ok, Req, Result} = service_available(Req0, #state{method=Method, handler=Handler, handler_state=HandlerState}), - {ok, Req, [{result, Result}|Env]}. + {ok, Req, Env#{result => Result}}. service_available(Req, State) -> expect(Req, State, service_available, true, fun known_methods/2, 503). @@ -1016,16 +1016,7 @@ set_resp_body(Req, State=#state{content_type_a={_, Callback}}) -> terminate(Req2, State#state{handler_state=HandlerState2}); {Body, Req2, HandlerState2} -> State2 = State#state{handler_state=HandlerState2}, - Req3 = case Body of - {stream, StreamFun} -> - cowboy_req:set_resp_body_fun(StreamFun, Req2); - {stream, Len, StreamFun} -> - cowboy_req:set_resp_body_fun(Len, StreamFun, Req2); - {chunked, StreamFun} -> - cowboy_req:set_resp_body_fun(chunked, StreamFun, Req2); - _ -> - cowboy_req:set_resp_body(Body, Req2) - end, + Req3 = cowboy_req:set_resp_body(Body, Req2), multiple_choices(Req3, State2) end catch Class:Reason = {case_clause, no_call} -> error_terminate(Req, State, Class, Reason) |