From 2d42ce4e10807b879b19ec42f7b9d50f1175f6a2 Mon Sep 17 00:00:00 2001 From: "Paulo F. Oliveira" Date: Thu, 27 Jul 2023 17:39:15 +0100 Subject: [PATCH 1/7] Update code for the new OTP 21-25 maintenance range In CI we also update some of the action tools' versions --- .github/workflows/main.yml | 41 +++++++++++++----- rebar.config | 6 +-- src/elli_http.erl | 87 ++++++++++++-------------------------- src/elli_tcp.erl | 13 ------ src/elli_util.hrl | 13 ------ test/elli_tests.erl | 6 --- 6 files changed, 60 insertions(+), 106 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6f7fbee..3dcb8ca 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,21 +10,43 @@ on: jobs: build: - name: Test on OTP ${{ matrix.otp_version }} and ${{ matrix.os }} - runs-on: ${{ matrix.os }} + name: Test on OTP ${{ matrix.tuple.otp_version }} and ${{ matrix.tuple.os }} + runs-on: ${{ matrix.tuple.os }} strategy: matrix: - otp_version: ['24', '23', '22', '21'] - os: [ubuntu-latest] + - tuple: + otp_version: 26 + os: ubuntu-22.04 + rebar3_version: 3.22 + - tuple: + otp_version: 25 + os: ubuntu-22.04 + rebar3_version: 3.22 + - tuple: + otp_version: 24 + os: ubuntu-22.04 + rebar3_version: 3.22 + - tuple: + otp_version: 23 + os: ubuntu-20.04 + rebar3_version: 3.15 + - tuple: + otp_version: 22 + os: ubuntu-20.04 + rebar3_version: 3.15 + - tuple: + otp_version: 21 + os: ubuntu-20.04 + rebar3_version: 3.15 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: erlef/setup-beam@v1 with: - otp-version: ${{ matrix.otp_version }} - rebar3-version: '3.14' + otp-version: ${{ matrix.tuple.otp_version }} + rebar3-version: ${{ matrix.tuple.rebar3_version }} - name: Compile run: rebar3 compile @@ -36,9 +58,8 @@ jobs: run: rebar3 xref - name: Covertool - if: ${{ always() }} run: rebar3 covertool generate - - uses: codecov/codecov-action@v1 + - uses: codecov/codecov-action@v3 with: - file: _build/test/covertool/elli.covertool.xml + files: _build/test/covertool/elli.covertool.xml env_vars: OTP_VERSION diff --git a/rebar.config b/rebar.config index 07ba484..9337286 100644 --- a/rebar.config +++ b/rebar.config @@ -1,9 +1,7 @@ {erl_first_files, ["src/elli_handler.erl"]}. {erl_opts, [debug_info, - {i, "include"}, - {platform_define, "^2", binary_http_uri}, - {platform_define, "^2[1-9]", post20}]}. -{minimum_otp_vsn, "20.0"}. + {i, "include"}]}. +{minimum_otp_vsn, "21.0"}. {deps, []}. {xref_checks, [undefined_function_calls,locals_not_used]}. {profiles, [ diff --git a/src/elli_http.erl b/src/elli_http.erl index 4404a76..812d733 100644 --- a/src/elli_http.erl +++ b/src/elli_http.erl @@ -323,17 +323,17 @@ execute_callback(#req{callback = {Mod, Args}} = Req) -> catch throw:{ResponseCode, Headers, Body} when is_integer(ResponseCode) -> {response, ResponseCode, Headers, Body}; - ?WITH_STACKTRACE(throw, Exc, Stacktrace) + throw:Exc:Stacktrace -> handle_event(Mod, request_throw, [Req, Exc, Stacktrace], Args), {response, 500, [], <<"Internal server error">>}; - ?WITH_STACKTRACE(error, Error, Stacktrace) + error:Error:Stacktrace -> handle_event(Mod, request_error, [Req, Error, Stacktrace], Args), {response, 500, [], <<"Internal server error">>}; - ?WITH_STACKTRACE(exit, Exit, Stacktrace) + exit:Exit:Stacktrace -> handle_event(Mod, request_exit, [Req, Exit, Stacktrace], Args), @@ -708,7 +708,6 @@ is_header_defined(Key, Headers) -> get_header(Key, Headers) -> get_header(Key, Headers, undefined). --ifdef(OTP_RELEASE). get_header(Key, Headers, Default) -> CaseFoldedKey = string:casefold(Key), case lists:search(fun({N, _}) -> string:equal(CaseFoldedKey, N, true) end, Headers) of @@ -717,67 +716,35 @@ get_header(Key, Headers, Default) -> false -> Default end. --else. -get_header(Key, Headers, Default) -> - CaseFoldedKey = string:casefold(Key), - case search(fun({N, _}) -> string:equal(CaseFoldedKey, N, true) end, Headers) of - {value, {_, Value}} -> - Value; - false -> - Default - end. - -search(Pred, [Hd|Tail]) -> - case Pred(Hd) of - true -> {value, Hd}; - false -> search(Pred, Tail) - end; -search(Pred, []) when is_function(Pred, 1) -> - false. --endif. %% %% PATH HELPERS %% --ifdef(OTP_RELEASE). - -if(?OTP_RELEASE >= 22). - parse_path({abs_path, FullPath}) -> - URIMap = uri_string:parse(FullPath), - Host = maps:get(host, URIMap, undefined), - Scheme = maps:get(scheme, URIMap, undefined), - Path = maps:get(path, URIMap, <<>>), - Query = maps:get(query, URIMap, <<>>), - Port = maps:get(port, URIMap, case Scheme of http -> 80; https -> 443; _ -> undefined end), - {ok, {Scheme, Host, Port}, {Path, split_path(Path), uri_string:dissect_query(Query)}}; - parse_path({absoluteURI, Scheme, Host, Port, Path}) -> - setelement(2, parse_path({abs_path, Path}), {Scheme, Host, Port}); - parse_path(_) -> - {error, unsupported_uri}. - -else. - parse_path({abs_path, FullPath}) -> - Parsed = case binary:split(FullPath, [<<"?">>]) of - [URL] -> {FullPath, split_path(URL), []}; - [URL, Args] -> {FullPath, split_path(URL), split_args(Args)} - end, - {ok, {undefined, undefined, undefined}, Parsed}; - parse_path({absoluteURI, Scheme, Host, Port, Path}) -> - setelement(2, parse_path({abs_path, Path}), {Scheme, Host, Port}); - parse_path(_) -> - {error, unsupported_uri}. - -endif. +-if(?OTP_RELEASE >= 22). +parse_path({abs_path, FullPath}) -> + URIMap = uri_string:parse(FullPath), + Host = maps:get(host, URIMap, undefined), + Scheme = maps:get(scheme, URIMap, undefined), + Path = maps:get(path, URIMap, <<>>), + Query = maps:get(query, URIMap, <<>>), + Port = maps:get(port, URIMap, case Scheme of http -> 80; https -> 443; _ -> undefined end), + {ok, {Scheme, Host, Port}, {Path, split_path(Path), uri_string:dissect_query(Query)}}; +parse_path({absoluteURI, Scheme, Host, Port, Path}) -> + setelement(2, parse_path({abs_path, Path}), {Scheme, Host, Port}); +parse_path(_) -> + {error, unsupported_uri}. -else. - %% same as else branch above. can drop this when only OTP 21+ is supported - parse_path({abs_path, FullPath}) -> - Parsed = case binary:split(FullPath, [<<"?">>]) of - [URL] -> {FullPath, split_path(URL), []}; - [URL, Args] -> {FullPath, split_path(URL), split_args(Args)} - end, - {ok, {undefined, undefined, undefined}, Parsed}; - parse_path({absoluteURI, Scheme, Host, Port, Path}) -> - setelement(2, parse_path({abs_path, Path}), {Scheme, Host, Port}); - parse_path(_) -> - {error, unsupported_uri}. +parse_path({abs_path, FullPath}) -> + Parsed = case binary:split(FullPath, [<<"?">>]) of + [URL] -> {FullPath, split_path(URL), []}; + [URL, Args] -> {FullPath, split_path(URL), split_args(Args)} + end, + {ok, {undefined, undefined, undefined}, Parsed}; +parse_path({absoluteURI, Scheme, Host, Port, Path}) -> + setelement(2, parse_path({abs_path, Path}), {Scheme, Host, Port}); +parse_path(_) -> + {error, unsupported_uri}. -endif. split_path(Path) -> @@ -813,7 +780,7 @@ handle_event(Mod, Name, EventArgs, ElliArgs) -> try Mod:handle_event(Name, EventArgs, ElliArgs) catch - ?WITH_STACKTRACE(EvClass, EvError, Stacktrace) + EvClass:EvError:Stacktrace -> ?LOG_ERROR("~p:handle_event/3 crashed ~p:~p~n~p", [Mod, EvClass, EvError, Stacktrace]) end. diff --git a/src/elli_tcp.erl b/src/elli_tcp.erl index ee9ad39..b0f3fdc 100644 --- a/src/elli_tcp.erl +++ b/src/elli_tcp.erl @@ -42,7 +42,6 @@ accept({ssl, Socket}, Server, Timeout) -> {error, Reason} end. --ifdef(post20). handshake(S, Server, Timeout) -> case ssl:handshake(S, Timeout) of {ok, S1} -> @@ -53,18 +52,6 @@ handshake(S, Server, Timeout) -> {error, Reason} -> {error, Reason} end. --else. -handshake(S, Server, Timeout) -> - case ssl:ssl_accept(S, Timeout) of - ok -> - gen_server:cast(Server, accepted), - {ok, {ssl, S}}; - {error, closed} -> - {error, econnaborted}; - {error, Reason} -> - {error, Reason} - end. --endif. recv({plain, Socket}, Size, Timeout) -> gen_tcp:recv(Socket, Size, Timeout); diff --git a/src/elli_util.hrl b/src/elli_util.hrl index 557ec28..e844c95 100644 --- a/src/elli_util.hrl +++ b/src/elli_util.hrl @@ -1,17 +1,4 @@ - --ifdef(OTP_RELEASE). -include_lib("kernel/include/logger.hrl"). --else. --define(LOG_ERROR(Str), error_logger:error_msg(Str)). --define(LOG_ERROR(Format,Data), error_logger:error_msg(Format, Data)). --define(LOG_INFO(Format,Data), error_logger:info_msg(Format, Data)). --endif. - --ifdef(OTP_RELEASE). --define(WITH_STACKTRACE(T, R, S), T:R:S ->). --else. --define(WITH_STACKTRACE(T, R, S), T:R -> S = erlang:get_stacktrace(),). --endif. %% Bloody useful -define(IF(Test,True,False), case Test of true -> True; false -> False end). diff --git a/test/elli_tests.erl b/test/elli_tests.erl index c89ba17..fb62ed1 100644 --- a/test/elli_tests.erl +++ b/test/elli_tests.erl @@ -7,13 +7,7 @@ -define(VTB(T1, T2, LB, UB), time_diff_to_micro_seconds(T1, T2) >= LB andalso time_diff_to_micro_seconds(T1, T2) =< UB). --ifdef(OTP_RELEASE). -include_lib("kernel/include/logger.hrl"). --else. --define(LOG_ERROR(Str), error_logger:error_msg(Str)). --define(LOG_ERROR(Format,Data), error_logger:error_msg(Format, Data)). --define(LOG_INFO(Format,Data), error_logger:info_msg(Format, Data)). --endif. time_diff_to_micro_seconds(T1, T2) -> erlang:convert_time_unit( From d57a50664cd1667062d792715d406ee32899a08c Mon Sep 17 00:00:00 2001 From: "Paulo F. Oliveira" Date: Thu, 27 Jul 2023 17:44:46 +0100 Subject: [PATCH 2/7] Update dep.s and plugins, get rid of erl_opts defaults ... and add warnings_as_errors --- rebar.config | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/rebar.config b/rebar.config index 9337286..ae9c1d9 100644 --- a/rebar.config +++ b/rebar.config @@ -1,8 +1,6 @@ {erl_first_files, ["src/elli_handler.erl"]}. -{erl_opts, [debug_info, - {i, "include"}]}. +{erl_opts, [debug_info, warnings_as_errors]}. {minimum_otp_vsn, "21.0"}. -{deps, []}. {xref_checks, [undefined_function_calls,locals_not_used]}. {profiles, [ {docs, [ @@ -16,15 +14,15 @@ ]} ]}, {test, [ - {deps, [{hackney, "1.17.4"}]} + {deps, [{hackney, "1.18.1"}]} ]} ]}. {shell, [{script_file, "bin/shell.escript"}]}. {project_plugins, [ - {covertool, "2.0.3"}, - {rebar3_lint, "v0.1.10"} + {covertool, "2.0.6"}, + {rebar3_lint, "1.0.2"} ]}. {provider_hooks, [{pre, [{eunit, lint}]}]}. From e4b484b6cf2aadd3edbc7ca269ad2028c874f328 Mon Sep 17 00:00:00 2001 From: "Paulo F. Oliveira" Date: Thu, 27 Jul 2023 17:53:41 +0100 Subject: [PATCH 3/7] Drop OTP 21 support --- .github/workflows/main.yml | 8 ++------ src/elli_http.erl | 13 ------------- 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3dcb8ca..7e2d63c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -30,15 +30,11 @@ jobs: - tuple: otp_version: 23 os: ubuntu-20.04 - rebar3_version: 3.15 + rebar3_version: 3.18 - tuple: otp_version: 22 os: ubuntu-20.04 - rebar3_version: 3.15 - - tuple: - otp_version: 21 - os: ubuntu-20.04 - rebar3_version: 3.15 + rebar3_version: 3.18 steps: - uses: actions/checkout@v3 diff --git a/src/elli_http.erl b/src/elli_http.erl index 812d733..cd549e4 100644 --- a/src/elli_http.erl +++ b/src/elli_http.erl @@ -721,7 +721,6 @@ get_header(Key, Headers, Default) -> %% PATH HELPERS %% --if(?OTP_RELEASE >= 22). parse_path({abs_path, FullPath}) -> URIMap = uri_string:parse(FullPath), Host = maps:get(host, URIMap, undefined), @@ -734,18 +733,6 @@ parse_path({absoluteURI, Scheme, Host, Port, Path}) -> setelement(2, parse_path({abs_path, Path}), {Scheme, Host, Port}); parse_path(_) -> {error, unsupported_uri}. --else. -parse_path({abs_path, FullPath}) -> - Parsed = case binary:split(FullPath, [<<"?">>]) of - [URL] -> {FullPath, split_path(URL), []}; - [URL, Args] -> {FullPath, split_path(URL), split_args(Args)} - end, - {ok, {undefined, undefined, undefined}, Parsed}; -parse_path({absoluteURI, Scheme, Host, Port, Path}) -> - setelement(2, parse_path({abs_path, Path}), {Scheme, Host, Port}); -parse_path(_) -> - {error, unsupported_uri}. --endif. split_path(Path) -> [P || P <- binary:split(Path, [<<"/">>], [global]), From 4826670405e8a47840e31167e8daf75ffdace279 Mon Sep 17 00:00:00 2001 From: "Paulo F. Oliveira" Date: Thu, 27 Jul 2023 17:57:06 +0100 Subject: [PATCH 4/7] Be stricter on XRef analysis --- rebar.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rebar.config b/rebar.config index ae9c1d9..d71d360 100644 --- a/rebar.config +++ b/rebar.config @@ -1,7 +1,7 @@ {erl_first_files, ["src/elli_handler.erl"]}. {erl_opts, [debug_info, warnings_as_errors]}. {minimum_otp_vsn, "21.0"}. -{xref_checks, [undefined_function_calls,locals_not_used]}. +{xref_checks, [deprecated_function_calls, undefined_function_calls, locals_not_used]}. {profiles, [ {docs, [ {deps, [{edown, "0.8.1"}]}, From 83309a7abcc54698edef4ef6b837016447be187e Mon Sep 17 00:00:00 2001 From: "Paulo F. Oliveira" Date: Thu, 27 Jul 2023 17:59:02 +0100 Subject: [PATCH 5/7] Be stricter on Dialyzer analysis and fix "new" issues --- rebar.config | 2 +- src/elli_example_callback.erl | 2 +- src/elli_middleware.erl | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rebar.config b/rebar.config index d71d360..35b55e6 100644 --- a/rebar.config +++ b/rebar.config @@ -26,7 +26,7 @@ ]}. {provider_hooks, [{pre, [{eunit, lint}]}]}. -{dialyzer, [{plt_extra_apps, [ssl]}]}. +{dialyzer, [{plt_extra_apps, [ssl]}, {warnings, [unknown]}]}. {cover_enabled, true}. {cover_export_enabled, true}. diff --git a/src/elli_example_callback.erl b/src/elli_example_callback.erl index 7eda4b8..355d1ed 100644 --- a/src/elli_example_callback.erl +++ b/src/elli_example_callback.erl @@ -297,7 +297,7 @@ chunk_loop(Ref, N) -> %% `file_error' is sent when the user wants to return a file as a %% response, but for some reason it cannot be opened. -spec handle_event(Event, Args, Config) -> ok when - Event :: elli:event(), + Event :: elli_handler:event(), Args :: elli_handler:callback_args(), Config :: [tuple()]. handle_event(elli_startup, [], _) -> ok; diff --git a/src/elli_middleware.erl b/src/elli_middleware.erl index 4a9cbae..3eaadca 100644 --- a/src/elli_middleware.erl +++ b/src/elli_middleware.erl @@ -86,7 +86,7 @@ handle_event(Event, Args, Config) -> -spec do_init(Req, Callbacks) -> {ok, standard | handover} when Req :: elli:req(), - Callbacks :: elli_handler:callbacks(). + Callbacks :: [elli_handler:callback()]. do_init(_, []) -> {ok, standard}; do_init(Req, [{Mod, Args}|Mods]) -> From 913aa81e46723395c52efa34216c6cdb230143f0 Mon Sep 17 00:00:00 2001 From: "Paulo F. Oliveira" Date: Thu, 27 Jul 2023 17:45:24 +0100 Subject: [PATCH 6/7] Be stricter on Elvis analysis and fix issues --- elvis.config | 33 +++++--------------------------- src/elli.erl | 14 +++++++------- src/elli_example_callback.erl | 2 +- src/elli_http.erl | 8 +++++--- src/elli_middleware.erl | 2 +- src/elli_request.erl | 15 ++++++++------- src/elli_sendfile.erl | 1 + src/elli_util.erl | 6 +++--- test/elli_metrics_middleware.erl | 4 ++-- test/elli_middleware_tests.erl | 8 ++++---- test/elli_ssl_tests.erl | 4 ++-- test/elli_tests.erl | 14 ++++++++------ 12 files changed, 47 insertions(+), 64 deletions(-) diff --git a/elvis.config b/elvis.config index c96c782..8bc0055 100644 --- a/elvis.config +++ b/elvis.config @@ -3,35 +3,12 @@ elvis, [ {config, - [#{dirs => [ - "src" - %% TODO: "test" - ], + [#{dirs => ["src", "test"], filter => "*.erl", - rules => [ - {elvis_style, no_tabs}, - {elvis_style, no_trailing_whitespace}, - {elvis_style, no_if_expression}, - {elvis_style, no_nested_try_catch}, - {elvis_style, invalid_dynamic_call, - #{ignore => [ - elli, - elli_http, - elli_middleware, - elli_test - ]}}, - {elvis_style, used_ignored_variable}, - {elvis_style, no_behavior_info}, - {elvis_style, state_record_and_type}, - {elvis_style, no_spec_with_records}, - {elvis_style, dont_repeat_yourself}, - {elvis_style, no_debug_call} - ], - ruleset => erl_files - }, - #{dirs => ["."], - filter => "Makefile", - ruleset => makefiles + ruleset => erl_files, + rules => [{elvis_style, no_throw, disable}, + {elvis_style, invalid_dynamic_call, disable}, + {elvis_style, dont_repeat_yourself, disable}] }, #{dirs => ["."], filter => "rebar.config", diff --git a/src/elli.erl b/src/elli.erl index 9f233ce..afee9a3 100644 --- a/src/elli.erl +++ b/src/elli.erl @@ -28,6 +28,7 @@ %% @type req(). A record representing an HTTP request. -type req() :: #req{}. +-elvis([{elvis_style, private_data_types, disable}]). %% @type http_method(). An uppercase atom representing a known HTTP verb or a %% binary for other verbs. @@ -37,7 +38,7 @@ %% @type body(). A binary or iolist. -type body() :: binary() | iolist(). --type header() :: {Key::binary(), Value::binary() | string()}. +-type header() :: {Key :: binary(), Value :: binary() | string()}. -type headers() :: [header()]. -type response_code() :: 100..999. @@ -162,12 +163,8 @@ init([Opts]) -> | SSLSockOpts]), Acceptors = ets:new(acceptors, [private, set]), - [begin - Pid = elli_http:start_link(self(), Socket, Options, - {Callback, CallbackArgs}), - ets:insert(Acceptors, {Pid}) - end - || _ <- lists:seq(1, MinAcceptors)], + [http_start(Socket, Options, Callback, CallbackArgs, Acceptors) + || _ <- lists:seq(1, MinAcceptors)], {ok, #state{socket = Socket, acceptors = Acceptors, @@ -175,6 +172,9 @@ init([Opts]) -> options = Options, callback = {Callback, CallbackArgs}}}. +http_start(Socket, Options, Callback, CallbackArgs, Acceptors) -> + Pid = elli_http:start_link(self(), Socket, Options, {Callback, CallbackArgs}), + ets:insert(Acceptors, {Pid}). %% @hidden -spec handle_call(get_acceptors, {pid(), _Tag}, state()) -> diff --git a/src/elli_example_callback.erl b/src/elli_example_callback.erl index 355d1ed..bf990c4 100644 --- a/src/elli_example_callback.erl +++ b/src/elli_example_callback.erl @@ -229,7 +229,7 @@ chunk_loop(Ref, N) -> {error, Reason} -> ?LOG_ERROR("error in sending chunk: ~p~n", [Reason]) end, - chunk_loop(Ref, N-1). + chunk_loop(Ref, N - 1). %% diff --git a/src/elli_http.erl b/src/elli_http.erl index cd549e4..cdefefd 100644 --- a/src/elli_http.erl +++ b/src/elli_http.erl @@ -36,6 +36,8 @@ -define(CONNECTION_HEADER, <<"connection">>). -define(TRANSFER_ENCODING_HEADER, <<"Transfer-Encoding">>). +-elvis([{elvis_style, max_function_arity, disable}]). + %% TODO: use this %% -type connection_token() :: keep_alive | close. @@ -58,7 +60,7 @@ start_link(Server, ListenSocket, Options, Callback) -> Options :: proplists:proplist(), Callback :: elli_handler:callback(). accept(Server, ListenSocket, Options, Callback) -> - case catch elli_tcp:accept(ListenSocket, Server, accept_timeout(Options)) of + case elli_tcp:accept(ListenSocket, Server, accept_timeout(Options)) of {ok, Socket} -> t(accepted), ?MODULE:keepalive_loop(Socket, Options, Callback); @@ -697,7 +699,7 @@ connection(Req, UserHeaders) -> [] end. -content_length(Headers, Body)-> +content_length(Headers, Body) -> ?IF(is_header_defined(?CONTENT_LENGTH_HEADER, Headers), [], {?CONTENT_LENGTH_HEADER, iolist_size(Body)}). @@ -729,7 +731,7 @@ parse_path({abs_path, FullPath}) -> Query = maps:get(query, URIMap, <<>>), Port = maps:get(port, URIMap, case Scheme of http -> 80; https -> 443; _ -> undefined end), {ok, {Scheme, Host, Port}, {Path, split_path(Path), uri_string:dissect_query(Query)}}; -parse_path({absoluteURI, Scheme, Host, Port, Path}) -> +parse_path({'absoluteURI', Scheme, Host, Port, Path}) -> setelement(2, parse_path({abs_path, Path}), {Scheme, Host, Port}); parse_path(_) -> {error, unsupported_uri}. diff --git a/src/elli_middleware.erl b/src/elli_middleware.erl index 3eaadca..f4dbed3 100644 --- a/src/elli_middleware.erl +++ b/src/elli_middleware.erl @@ -89,7 +89,7 @@ handle_event(Event, Args, Config) -> Callbacks :: [elli_handler:callback()]. do_init(_, []) -> {ok, standard}; -do_init(Req, [{Mod, Args}|Mods]) -> +do_init(Req, [{Mod, Args} | Mods]) -> ?IF_NOT_EXPORTED(Mod, init, 2, do_init(Req, Mods), case Mod:init(Req, Args) of ignore -> do_init(Req, Mods); diff --git a/src/elli_request.erl b/src/elli_request.erl index 6500ee2..47057dc 100644 --- a/src/elli_request.erl +++ b/src/elli_request.erl @@ -40,10 +40,11 @@ -export_type([http_range/0]). --type http_range() :: {First::non_neg_integer(), Last::non_neg_integer()} - | {offset, Offset::non_neg_integer()} - | {suffix, Length::pos_integer()}. +-type http_range() :: {First :: non_neg_integer(), Last :: non_neg_integer()} + | {offset, Offset :: non_neg_integer()} + | {suffix, Length :: pos_integer()}. +-elvis([{elvis_style, god_modules, disable}]). %% %% Helpers for working with a #req{} @@ -184,7 +185,7 @@ get_range(#req{headers = Headers}) -> end. --spec parse_range_set(Bin::binary()) -> [http_range()] | parse_error. +-spec parse_range_set(Bin :: binary()) -> [http_range()] | parse_error. parse_range_set(<>) -> RangeBins = binary:split(ByteRangeSet, <<",">>, [global]), Parsed = [parse_range(remove_whitespace(RangeBin)) @@ -194,7 +195,7 @@ parse_range_set(<>) -> false -> Parsed end. --spec parse_range(Bin::binary()) -> http_range() | parse_error. +-spec parse_range(Bin :: binary()) -> http_range() | parse_error. parse_range(<<$-, SuffixBin/binary>>) -> %% suffix-byte-range try {suffix, binary_to_integer(SuffixBin)} @@ -295,5 +296,5 @@ uri_decode(<>, Acc) -> -compile({inline, [hex_to_int/1]}). hex_to_int(X) when X >= $0, X =< $9 -> X - $0; -hex_to_int(X) when X >= $a, X =< $f -> X - ($a-10); -hex_to_int(X) when X >= $A, X =< $F -> X - ($A-10). +hex_to_int(X) when X >= $a, X =< $f -> X - ($a - 10); +hex_to_int(X) when X >= $A, X =< $F -> X - ($A - 10). diff --git a/src/elli_sendfile.erl b/src/elli_sendfile.erl index d67ded4..5a11a67 100644 --- a/src/elli_sendfile.erl +++ b/src/elli_sendfile.erl @@ -6,6 +6,7 @@ -export([sendfile/5]). -type sendfile_opts() :: [{chunk_size, non_neg_integer()}]. +-export_type([sendfile_opts/0]). %% @doc Send part of a file on a socket. %% diff --git a/src/elli_util.erl b/src/elli_util.erl index b8aa5cf..17ecbbe 100644 --- a/src/elli_util.erl +++ b/src/elli_util.erl @@ -11,7 +11,7 @@ -export_type([range/0]). --type range() :: {Offset::non_neg_integer(), Length::non_neg_integer()}. +-type range() :: {Offset :: non_neg_integer(), Length :: non_neg_integer()}. -spec normalize_range(RangeOrSet, Size) -> Normalized when RangeOrSet :: any(), @@ -42,8 +42,8 @@ normalize_range([], _Size) -> undefined; normalize_range(_, _Size) -> invalid_range. --spec encode_range(Range::range() | invalid_range, - Size::non_neg_integer()) -> ByteRange::iolist(). +-spec encode_range(Range :: range() | invalid_range, + Size :: non_neg_integer()) -> ByteRange :: iolist(). %% @doc: Encode Range to a Content-Range value. encode_range(Range, Size) -> [<<"bytes ">>, encode_range_bytes(Range), diff --git a/test/elli_metrics_middleware.erl b/test/elli_metrics_middleware.erl index 3861c68..76c9cfe 100644 --- a/test/elli_metrics_middleware.erl +++ b/test/elli_metrics_middleware.erl @@ -24,10 +24,10 @@ postprocess(_Req, Res, _Args) -> %% ELLI EVENT CALLBACKS %% -handle_event(request_complete, [_Req,_C,_Hs,_B, {Timings, Sizes}], _) -> +handle_event(request_complete, [_Req, _C, _Hs, _B, {Timings, Sizes}], _) -> ets:insert(elli_stat_table, {timings, Timings}), ets:insert(elli_stat_table, {sizes, Sizes}); -handle_event(chunk_complete, [_Req,_C,_Hs,_B, {Timings, Sizes}], _) -> +handle_event(chunk_complete, [_Req, _C, _Hs, _B, {Timings, Sizes}], _) -> ets:insert(elli_stat_table, {timings, Timings}), ets:insert(elli_stat_table, {sizes, Sizes}); handle_event(_Event, _Data, _Args) -> diff --git a/test/elli_middleware_tests.erl b/test/elli_middleware_tests.erl index ea303ee..38e2bcb 100644 --- a/test/elli_middleware_tests.erl +++ b/test/elli_middleware_tests.erl @@ -28,9 +28,9 @@ hello_world() -> ?assertMatch(<<"Hello World!">>, body(Response)). compress() -> - Url = "http://localhost:3002/compressed", + URL = "http://localhost:3002/compressed", Headers = [{<<"Accept-Encoding">>, <<"gzip">>}], - Response = hackney:get(Url, Headers), + Response = hackney:get(URL, Headers), ?assertHeadersEqual([{<<"Connection">>, <<"Keep-Alive">>}, {<<"Content-Encoding">>, <<"gzip">>}, {<<"Content-Length">>, <<"41">>}], @@ -43,9 +43,9 @@ compress() -> headers(Response1)), ?assertEqual(iolist_to_binary(lists:duplicate(86, "Hello World!")), body(Response1)), - Url2 = "http://localhost:3002/compressed-io_list", + URL2 = "http://localhost:3002/compressed-io_list", Headers2 = [{<<"Accept-Encoding">>, <<"gzip">>}], - Response2 = hackney:get(Url2, Headers2), + Response2 = hackney:get(URL2, Headers2), ?assertMatch(200, status(Response2)), ?assertHeadersEqual([{<<"Connection">>, <<"Keep-Alive">>}, {<<"Content-Encoding">>, <<"gzip">>}, diff --git a/test/elli_ssl_tests.erl b/test/elli_ssl_tests.erl index 7a7d1d5..7fb40d8 100644 --- a/test/elli_ssl_tests.erl +++ b/test/elli_ssl_tests.erl @@ -41,7 +41,7 @@ chunked() -> ?assertMatch(200, status(Response)), ?assertHeadersEqual([{<<"connection">>, <<"Keep-Alive">>}, {<<"content-type">>, <<"text/event-stream">>}, - {<<"transfer-encoding">>,<<"chunked">>}], headers(Response)), + {<<"transfer-encoding">>, <<"chunked">>}], headers(Response)), ?assertMatch(Expected, body(Response)). sendfile() -> @@ -71,7 +71,7 @@ sendfile() -> acceptor_leak_regression() -> {ok, Before} = elli:get_acceptors(elli_under_test), Opts = [{verify, verify_peer}, - {verify_fun, {fun(_,_) -> {fail, 23} end, []}}, + {verify_fun, {fun(_, _) -> {fail, 23} end, []}}, {reuse_sessions, false}], {error, _} = ssl:connect("localhost", 3443, Opts), {ok, After} = elli:get_acceptors(elli_under_test), diff --git a/test/elli_tests.erl b/test/elli_tests.erl index fb62ed1..7b3080c 100644 --- a/test/elli_tests.erl +++ b/test/elli_tests.erl @@ -196,8 +196,8 @@ keep_alive_timings() -> keep_alive_timings(Status, Headers, HCRef) -> ?assertMatch(200, Status), - ?assertHeadersEqual([{<<"connection">>,<<"Keep-Alive">>}, - {<<"content-length">>,<<"12">>}], Headers), + ?assertHeadersEqual([{<<"connection">>, <<"Keep-Alive">>}, + {<<"content-length">>, <<"12">>}], Headers), ?assertMatch({ok, <<"Hello World!">>}, hackney:body(HCRef)), %% sizes ?assertMatch(63, get_size_value(resp_headers)), @@ -472,7 +472,8 @@ sendfile_range() -> ?assertMatch(206, status(Response)), ?assertHeadersEqual([{<<"connection">>, <<"Keep-Alive">>}, {<<"content-length">>, <<"400">>}, - {<<"Content-Range">>, iolist_to_binary(["bytes 300-699/", integer_to_binary(Size)])}], + {<<"Content-Range">>, + iolist_to_binary(["bytes 300-699/", integer_to_binary(Size)])}], headers(Response)), ?assertEqual(Expected, body(Response)). @@ -717,7 +718,7 @@ normalize_range_test_() -> encode_range_test() -> - Expected = [<<"bytes ">>,<<"*">>,<<"/">>,<<"42">>], + Expected = [<<"bytes ">>, <<"*">>, <<"/">>, <<"42">>], ?assertMatch(Expected, elli_util:encode_range(invalid_range, 42)). register_test() -> @@ -735,7 +736,8 @@ register_test() -> ok. invalid_callback_test() -> - case catch elli:start_link([{callback, elli}]) of - E -> + try + elli:start_link([{callback, elli}]) + catch throw:E -> ?assertMatch(invalid_callback, E) end. From 66f17c60764eace7491a73bf67307f36dd811ae7 Mon Sep 17 00:00:00 2001 From: "Paulo F. Oliveira" Date: Thu, 27 Jul 2023 21:54:56 +0100 Subject: [PATCH 7/7] Update CI --- .github/workflows/main.yml | 47 +++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7e2d63c..9940c28 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,29 +10,23 @@ on: jobs: build: - name: Test on OTP ${{ matrix.tuple.otp_version }} and ${{ matrix.tuple.os }} - runs-on: ${{ matrix.tuple.os }} + name: Test on OTP ${{ matrix.otp_version }} and ${{ matrix.os }} + runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: - - tuple: - otp_version: 26 + include: + - otp_version: 25 os: ubuntu-22.04 rebar3_version: 3.22 - - tuple: - otp_version: 25 + - otp_version: 24 os: ubuntu-22.04 rebar3_version: 3.22 - - tuple: - otp_version: 24 - os: ubuntu-22.04 - rebar3_version: 3.22 - - tuple: - otp_version: 23 + - otp_version: 23 os: ubuntu-20.04 rebar3_version: 3.18 - - tuple: - otp_version: 22 + - otp_version: 22 os: ubuntu-20.04 rebar3_version: 3.18 @@ -40,9 +34,30 @@ jobs: - uses: actions/checkout@v3 - uses: erlef/setup-beam@v1 + id: setup-beam + with: + otp-version: ${{ matrix.otp_version }} + rebar3-version: ${{ matrix.rebar3_version }} + + - name: Restore _build + uses: actions/cache@v3 + with: + path: _build + key: "_build-cache-for\ + -os-${{ matrix.os }}\ + -otp-${{ steps.setup-beam.outputs.otp-version }}\ + -rebar3-${{ steps.setup-beam.outputs.rebar3-version }}\ + -hash-${{ hashFiles('rebar.lock') }}" + + - name: Restore rebar3's cache + uses: actions/cache@v3 with: - otp-version: ${{ matrix.tuple.otp_version }} - rebar3-version: ${{ matrix.tuple.rebar3_version }} + path: ~/.cache/rebar3 + key: "rebar3-cache-for\ + -os-${{ matrix.os }}\ + -otp-${{ steps.setup-beam.outputs.otp-version }}\ + -rebar3-${{ steps.setup-beam.outputs.rebar3-version }}\ + -hash-${{ hashFiles('rebar.lock') }}" - name: Compile run: rebar3 compile