Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:

strategy:
matrix:
otp_version: [25,26,27]
otp_version: [26,27,28]
os: [ubuntu-latest]

container:
Expand Down
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,4 @@ doc/*
!doc/img
!doc/img/*
!doc/img/logo.png
*.lock
.vscode
3 changes: 2 additions & 1 deletion rebar.config
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@

{deps, [
{zotonic_stdlib, "~> 1.6"},
{cowboy, "2.9.0"}
{cowlib, "~> 2.16"},
{cowboy, "~> 2.14"}
]}.

{profiles, [
Expand Down
28 changes: 28 additions & 0 deletions rebar.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{"1.2.0",
[{<<"cowboy">>,{pkg,<<"cowboy">>,<<"2.9.0">>},0},
{<<"cowlib">>,{pkg,<<"cowlib">>,<<"2.16.0">>},0},
{<<"qdate_localtime">>,{pkg,<<"qdate_localtime">>,<<"1.2.1">>},1},
{<<"ranch">>,{pkg,<<"ranch">>,<<"1.8.0">>},1},
{<<"ssl_verify_fun">>,{pkg,<<"ssl_verify_fun">>,<<"1.1.7">>},2},
{<<"tls_certificate_check">>,
{pkg,<<"tls_certificate_check">>,<<"1.29.0">>},
1},
{<<"zotonic_stdlib">>,{pkg,<<"zotonic_stdlib">>,<<"1.24.0">>},0}]}.
[
{pkg_hash,[
{<<"cowboy">>, <<"865DD8B6607E14CF03282E10E934023A1BD8BE6F6BACF921A7E2A96D800CD452">>},
{<<"cowlib">>, <<"54592074EBBBB92EE4746C8A8846E5605052F29309D3A873468D76CDF932076F">>},
{<<"qdate_localtime">>, <<"72E1034DC6B7FEE8F588281EDDD0BD0DC5260005D758052F50634D265D382C18">>},
{<<"ranch">>, <<"8C7A100A139FD57F17327B6413E4167AC559FBC04CA7448E9BE9057311597A1D">>},
{<<"ssl_verify_fun">>, <<"354C321CF377240C7B8716899E182CE4890C5938111A1296ADD3EC74CF1715DF">>},
{<<"tls_certificate_check">>, <<"4473005EB0BBDAD215D7083A230E2E076F538D9EA472C8009FD22006A4CFC5F6">>},
{<<"zotonic_stdlib">>, <<"31456B4C25B41043B83E539C25FF387C5594BE8542906242DC4E07FAE1B81844">>}]},
{pkg_hash_ext,[
{<<"cowboy">>, <<"2C729F934B4E1AA149AFF882F57C6372C15399A20D54F65C8D67BEF583021BDE">>},
{<<"cowlib">>, <<"7F478D80D66B747344F0EA7708C187645CFCC08B11AA424632F78E25BF05DB51">>},
{<<"qdate_localtime">>, <<"1109958D205C65C595C8C5694CB83EBAF2DBE770CF902E4DCE8AFB2C4123764D">>},
{<<"ranch">>, <<"49FBCFD3682FAB1F5D109351B61257676DA1A2FDBE295904176D5E521A2DDFE5">>},
{<<"ssl_verify_fun">>, <<"FE4C190E8F37401D30167C8C405EDA19469F34577987C76DDE613E838BBC67F8">>},
{<<"tls_certificate_check">>, <<"5B0D0E5CB0F928BC4F210DF667304ED91C5BFF2A391CE6BDEDFBFE70A8F096C5">>},
{<<"zotonic_stdlib">>, <<"BC626DE1E5884E4695DA91A1169A0797D13F8EE933FE1C5452B9C10EFABADA03">>}]}
].
2 changes: 1 addition & 1 deletion src/cowmachine_decision_core.erl
Original file line number Diff line number Diff line change
Expand Up @@ -847,7 +847,7 @@ is_if_range_ok(<<$", _/binary>> = IfETag, ETag, _LM) ->
lists:member(ETag, ETags);
is_if_range_ok(Date, _ETag, LM) ->
ErlDate = cowmachine_util:convert_request_date(Date),
ErlDate =/= undefined andalso ErlDate >= LM.
ErlDate =/= bad_date andalso ErlDate >= LM.


choose_content_encoding(AccEncHdr, State, Context) ->
Expand Down
24 changes: 20 additions & 4 deletions src/cowmachine_response.erl
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
]).

-define(FILE_CHUNK_LENGTH, 16#80000). % 512KB
-define(DEFAULT_IDLE_TIMEOUT, 60000).

%% @doc Returns server header.
-spec server_header() -> Result when
Expand Down Expand Up @@ -116,8 +117,6 @@ send_response_code(Code, Parts, Context) ->
Parts :: cowmachine_req:parts(),
Context :: cowmachine_req:context(),
Result :: cowmachine_req:context().
% send_response_bodyfun(undefined, Code, Parts, Context) ->
% send_response_bodyfun(<<>>, Code, Parts, Context);
send_response_bodyfun({device, IO}, Code, Parts, Context) ->
Length = iodevice_size(IO),
send_response_bodyfun({device, Length, IO}, Code, Parts, Context);
Expand Down Expand Up @@ -191,11 +190,14 @@ send_response_bodyfun(Body, Code, all, Context) ->
Req1 = cowboy_req:reply(Code, Headers, Body, Req),
cowmachine_req:set_req(Req1, Context);
send_response_bodyfun(Body, Code, Parts, Context) ->
set_idle_timeout(infinity, Context),
Headers = response_headers(Context),
Req = cowmachine_req:req(Context),
Req1 = cowboy_req:stream_reply(Code, Headers, Req),
Context1 = cowmachine_req:set_req(Req1, Context),
send_parts(Context1, Parts, iolist_to_binary(Body)).
Context2 = send_parts(Context1, Parts, iolist_to_binary(Body)),
set_idle_timeout(?DEFAULT_IDLE_TIMEOUT, Context2),
Context2.

-spec start_response_stream(Code, Length, InitialStream, Parts, Context) -> Result when
Code :: integer(),
Expand All @@ -205,6 +207,7 @@ send_response_bodyfun(Body, Code, Parts, Context) ->
Context :: cowmachine_req:context(),
Result :: cowmachine_req:context().
start_response_stream(Code, Length, InitialStream, Parts, Context) ->
set_idle_timeout(infinity, Context),
{Code1, Context1, Parts1} = case is_streaming_range(InitialStream) of
false when Parts =/= all ->
% Drop range response header
Expand All @@ -227,7 +230,9 @@ start_response_stream(Code, Length, InitialStream, Parts, Context) ->
InitialFun ->
stream_initial_fun(InitialFun, Parts1)
end,
send_stream_body(FirstHunk, Context2).
Context3 = send_stream_body(FirstHunk, Context2),
set_idle_timeout(?DEFAULT_IDLE_TIMEOUT, Context3),
Context3.

-spec stream_initial_fun(Fun, Parts) -> Result when
Fun :: function(),
Expand All @@ -240,6 +245,17 @@ stream_initial_fun(F, _Parts) when is_function(F) ->
stream_initial_fun(done, _Parts) ->
done.

%% @doc Set the idle timeout for the connection. This will reset the idle timeout
%% timer for HTTP/1.x connections. During streaming we do not want a timeout.
%% The default is 60 seconds.
-spec set_idle_timeout(Timeout, Context) -> ok when
Timeout :: pos_integer() | infinity,
Context :: cowmachine_req:context().
set_idle_timeout(Timeout, Context) ->
Req = cowmachine_req:req(Context),
cowboy_req:cast({set_options, #{
idle_timeout => Timeout
}}, Req).

%% @doc Check if we support ranges on the data stream (body or function)
-spec is_streaming_range(Stream) -> Result when
Expand Down
2 changes: 1 addition & 1 deletion src/cowmachine_util.erl
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ valid_location(Location) ->

-spec convert_request_date(Date) -> Result when
Date :: binary(),
Result :: calendar:datetime().
Result :: calendar:datetime() | bad_date.
convert_request_date(Date) ->
try
cow_date:parse_date(Date)
Expand Down