aboutsummaryrefslogtreecommitdiffstats
path: root/src/cowboy_protocol.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/cowboy_protocol.erl')
-rw-r--r--src/cowboy_protocol.erl58
1 files changed, 46 insertions, 12 deletions
diff --git a/src/cowboy_protocol.erl b/src/cowboy_protocol.erl
index 2da3a15..b1cdc3a 100644
--- a/src/cowboy_protocol.erl
+++ b/src/cowboy_protocol.erl
@@ -55,6 +55,7 @@
}).
-include_lib("cowlib/include/cow_inline.hrl").
+-include_lib("cowlib/include/cow_parse.hrl").
%% API.
@@ -264,13 +265,12 @@ match_colon(<< _, Rest/bits >>, N) ->
match_colon(_, _) ->
nomatch.
+parse_hd_name(<< $:, Rest/bits >>, S, M, P, Q, V, H, SoFar) ->
+ parse_hd_before_value(Rest, S, M, P, Q, V, H, SoFar);
+parse_hd_name(<< C, Rest/bits >>, S, M, P, Q, V, H, SoFar) when ?IS_WS(C) ->
+ parse_hd_name_ws(Rest, S, M, P, Q, V, H, SoFar);
parse_hd_name(<< C, Rest/bits >>, S, M, P, Q, V, H, SoFar) ->
- case C of
- $: -> parse_hd_before_value(Rest, S, M, P, Q, V, H, SoFar);
- $\s -> parse_hd_name_ws(Rest, S, M, P, Q, V, H, SoFar);
- $\t -> parse_hd_name_ws(Rest, S, M, P, Q, V, H, SoFar);
- ?INLINE_LOWERCASE(parse_hd_name, Rest, S, M, P, Q, V, H, SoFar)
- end.
+ ?LOWER(parse_hd_name, Rest, S, M, P, Q, V, H, SoFar).
parse_hd_name_ws(<< C, Rest/bits >>, S, M, P, Q, V, H, Name) ->
case C of
@@ -348,7 +348,7 @@ parse_hd_value(<< $\r, Rest/bits >>, S, M, P, Q, V, Headers, Name, SoFar) ->
parse_hd_value(Rest2, S, M, P, Q, V, Headers, Name,
<< SoFar/binary, C >>);
<< $\n, Rest2/bits >> ->
- parse_header(Rest2, S, M, P, Q, V, [{Name, SoFar}|Headers])
+ parse_header(Rest2, S, M, P, Q, V, [{Name, clean_value_ws_end(SoFar, byte_size(SoFar) - 1)}|Headers])
end;
parse_hd_value(<< C, Rest/bits >>, S, M, P, Q, V, H, N, SoFar) ->
parse_hd_value(Rest, S, M, P, Q, V, H, N, << SoFar/binary, C >>);
@@ -358,6 +358,42 @@ parse_hd_value(<<>>, State=#state{max_header_value_length=MaxLength},
parse_hd_value(<<>>, S, M, P, Q, V, H, N, SoFar) ->
wait_hd_value(<<>>, S, M, P, Q, V, H, N, SoFar).
+clean_value_ws_end(_, -1) ->
+ <<>>;
+clean_value_ws_end(Value, N) ->
+ case binary:at(Value, N) of
+ $\s -> clean_value_ws_end(Value, N - 1);
+ $\t -> clean_value_ws_end(Value, N - 1);
+ _ ->
+ S = N + 1,
+ << Value2:S/binary, _/bits >> = Value,
+ Value2
+ end.
+
+-ifdef(TEST).
+clean_value_ws_end_test_() ->
+ Tests = [
+ {<<>>, <<>>},
+ {<<" ">>, <<>>},
+ {<<"text/*;q=0.3, text/html;q=0.7, text/html;level=1, "
+ "text/html;level=2;q=0.4, */*;q=0.5 \t \t ">>,
+ <<"text/*;q=0.3, text/html;q=0.7, text/html;level=1, "
+ "text/html;level=2;q=0.4, */*;q=0.5">>}
+ ],
+ [{V, fun() -> R = clean_value_ws_end(V, byte_size(V) - 1) end} || {V, R} <- Tests].
+-endif.
+
+-ifdef(PERF).
+horse_clean_value_ws_end() ->
+ horse:repeat(200000,
+ clean_value_ws_end(
+ <<"text/*;q=0.3, text/html;q=0.7, text/html;level=1, "
+ "text/html;level=2;q=0.4, */*;q=0.5 ">>,
+ byte_size(<<"text/*;q=0.3, text/html;q=0.7, text/html;level=1, "
+ "text/html;level=2;q=0.4, */*;q=0.5 ">>) - 1)
+ ).
+-endif.
+
request(B, State=#state{transport=Transport}, M, P, Q, Version, Headers) ->
case lists:keyfind(<<"host">>, 1, Headers) of
false when Version =:= 'HTTP/1.1' ->
@@ -393,9 +429,7 @@ parse_host(<< $:, Rest/bits >>, false, Acc) ->
parse_host(<< $], Rest/bits >>, true, Acc) ->
parse_host(Rest, false, << Acc/binary, $] >>);
parse_host(<< C, Rest/bits >>, E, Acc) ->
- case C of
- ?INLINE_LOWERCASE(parse_host, Rest, E, Acc)
- end.
+ ?LOWER(parse_host, Rest, E, Acc).
%% End of request parsing.
%%
@@ -431,7 +465,7 @@ execute(Req, State, Env, [Middleware|Tail]) ->
{suspend, Module, Function, Args} ->
erlang:hibernate(?MODULE, resume,
[State, Env, Tail, Module, Function, Args]);
- {halt, Req2} ->
+ {stop, Req2} ->
next_request(Req2, State, ok)
end.
@@ -444,7 +478,7 @@ resume(State, Env, Tail, Module, Function, Args) ->
{suspend, Module2, Function2, Args2} ->
erlang:hibernate(?MODULE, resume,
[State, Env, Tail, Module2, Function2, Args2]);
- {halt, Req2} ->
+ {stop, Req2} ->
next_request(Req2, State, ok)
end.