mirror of
https://github.com/ninenines/cowboy.git
synced 2025-07-14 20:30:23 +00:00
Stop using binary:match in cowboy_protocol
It's been found slower than a custom equivalent to what we were using it for. As this is the critical path we prefer the custom solution.
This commit is contained in:
parent
233cf43ab9
commit
a930f4ab26
1 changed files with 22 additions and 8 deletions
|
@ -171,20 +171,27 @@ parse_request(<< $\n, _/binary >>, State, _) ->
|
||||||
%% reading from the socket and eventually crashing.
|
%% reading from the socket and eventually crashing.
|
||||||
parse_request(Buffer, State=#state{max_request_line_length=MaxLength,
|
parse_request(Buffer, State=#state{max_request_line_length=MaxLength,
|
||||||
max_empty_lines=MaxEmpty}, ReqEmpty) ->
|
max_empty_lines=MaxEmpty}, ReqEmpty) ->
|
||||||
case binary:match(Buffer, <<"\n">>) of
|
case match_eol(Buffer, 0) of
|
||||||
nomatch when byte_size(Buffer) > MaxLength ->
|
nomatch when byte_size(Buffer) > MaxLength ->
|
||||||
error_terminate(414, State);
|
error_terminate(414, State);
|
||||||
nomatch ->
|
nomatch ->
|
||||||
wait_request(Buffer, State, ReqEmpty);
|
wait_request(Buffer, State, ReqEmpty);
|
||||||
{1, _} when ReqEmpty =:= MaxEmpty ->
|
1 when ReqEmpty =:= MaxEmpty ->
|
||||||
error_terminate(400, State);
|
error_terminate(400, State);
|
||||||
{1, _} ->
|
1 ->
|
||||||
<< _:16, Rest/binary >> = Buffer,
|
<< _:16, Rest/binary >> = Buffer,
|
||||||
parse_request(Rest, State, ReqEmpty + 1);
|
parse_request(Rest, State, ReqEmpty + 1);
|
||||||
{_, _} ->
|
_ ->
|
||||||
parse_method(Buffer, State, <<>>)
|
parse_method(Buffer, State, <<>>)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
match_eol(<< $\n, _/bits >>, N) ->
|
||||||
|
N;
|
||||||
|
match_eol(<< _, Rest/bits >>, N) ->
|
||||||
|
match_eol(Rest, N + 1);
|
||||||
|
match_eol(_, _) ->
|
||||||
|
nomatch.
|
||||||
|
|
||||||
parse_method(<< C, Rest/bits >>, State, SoFar) ->
|
parse_method(<< C, Rest/bits >>, State, SoFar) ->
|
||||||
case C of
|
case C of
|
||||||
$\r -> error_terminate(400, State);
|
$\r -> error_terminate(400, State);
|
||||||
|
@ -261,15 +268,22 @@ parse_header(<< $\r, $\n, Rest/bits >>, S, M, P, Q, F, V, Headers) ->
|
||||||
request(Rest, S, M, P, Q, F, V, lists:reverse(Headers));
|
request(Rest, S, M, P, Q, F, V, lists:reverse(Headers));
|
||||||
parse_header(Buffer, State=#state{max_header_name_length=MaxLength},
|
parse_header(Buffer, State=#state{max_header_name_length=MaxLength},
|
||||||
M, P, Q, F, V, H) ->
|
M, P, Q, F, V, H) ->
|
||||||
case binary:match(Buffer, <<":">>) of
|
case match_colon(Buffer, 0) of
|
||||||
nomatch when byte_size(Buffer) > MaxLength ->
|
nomatch when byte_size(Buffer) > MaxLength ->
|
||||||
error_terminate(400, State);
|
error_terminate(400, State);
|
||||||
nomatch ->
|
nomatch ->
|
||||||
wait_header(Buffer, State, M, P, Q, F, V, H);
|
wait_header(Buffer, State, M, P, Q, F, V, H);
|
||||||
{_, _} ->
|
_ ->
|
||||||
parse_hd_name(Buffer, State, M, P, Q, F, V, H, <<>>)
|
parse_hd_name(Buffer, State, M, P, Q, F, V, H, <<>>)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
match_colon(<< $:, _/bits >>, N) ->
|
||||||
|
N;
|
||||||
|
match_colon(<< _, Rest/bits >>, N) ->
|
||||||
|
match_colon(Rest, N + 1);
|
||||||
|
match_colon(_, _) ->
|
||||||
|
nomatch.
|
||||||
|
|
||||||
%% I know, this isn't exactly pretty. But this is the most critical
|
%% I know, this isn't exactly pretty. But this is the most critical
|
||||||
%% code path and as such needs to be optimized to death.
|
%% code path and as such needs to be optimized to death.
|
||||||
%%
|
%%
|
||||||
|
@ -336,12 +350,12 @@ parse_hd_before_value(<< $\t, Rest/bits >>, S, M, P, Q, F, V, H, N) ->
|
||||||
parse_hd_before_value(Rest, S, M, P, Q, F, V, H, N);
|
parse_hd_before_value(Rest, S, M, P, Q, F, V, H, N);
|
||||||
parse_hd_before_value(Buffer, State=#state{
|
parse_hd_before_value(Buffer, State=#state{
|
||||||
max_header_value_length=MaxLength}, M, P, Q, F, V, H, N) ->
|
max_header_value_length=MaxLength}, M, P, Q, F, V, H, N) ->
|
||||||
case binary:match(Buffer, <<"\n">>) of
|
case match_eol(Buffer, 0) of
|
||||||
nomatch when byte_size(Buffer) > MaxLength ->
|
nomatch when byte_size(Buffer) > MaxLength ->
|
||||||
error_terminate(400, State);
|
error_terminate(400, State);
|
||||||
nomatch ->
|
nomatch ->
|
||||||
wait_hd_before_value(Buffer, State, M, P, Q, F, V, H, N);
|
wait_hd_before_value(Buffer, State, M, P, Q, F, V, H, N);
|
||||||
{_, _} ->
|
_ ->
|
||||||
parse_hd_value(Buffer, State, M, P, Q, F, V, H, N, <<>>)
|
parse_hd_value(Buffer, State, M, P, Q, F, V, H, N, <<>>)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue