mirror of
https://github.com/ninenines/cowboy.git
synced 2025-07-14 12:20:24 +00:00
Add an option to disable sendfile for a listener
This commit is contained in:
parent
571719a164
commit
be09711687
5 changed files with 48 additions and 8 deletions
|
@ -32,6 +32,7 @@ opts() :: #{
|
||||||
max_skip_body_length => non_neg_integer(),
|
max_skip_body_length => non_neg_integer(),
|
||||||
middlewares => [module()],
|
middlewares => [module()],
|
||||||
request_timeout => timeout(),
|
request_timeout => timeout(),
|
||||||
|
sendfile => boolean(),
|
||||||
shutdown_timeout => timeout(),
|
shutdown_timeout => timeout(),
|
||||||
stream_handlers => [module()]
|
stream_handlers => [module()]
|
||||||
}
|
}
|
||||||
|
@ -96,6 +97,11 @@ middlewares ([cowboy_router, cowboy_handler])::
|
||||||
request_timeout (5000)::
|
request_timeout (5000)::
|
||||||
Time in ms with no requests before Cowboy closes the connection.
|
Time in ms with no requests before Cowboy closes the connection.
|
||||||
|
|
||||||
|
sendfile (true)::
|
||||||
|
Whether the sendfile syscall may be used. It can be useful to disable
|
||||||
|
it on systems where the syscall has a buggy implementation, for example
|
||||||
|
under VirtualBox when using shared folders.
|
||||||
|
|
||||||
shutdown_timeout (5000)::
|
shutdown_timeout (5000)::
|
||||||
Time in ms Cowboy will wait for child processes to shut down before killing them.
|
Time in ms Cowboy will wait for child processes to shut down before killing them.
|
||||||
|
|
||||||
|
@ -104,6 +110,7 @@ stream_handlers ([cowboy_stream_h])::
|
||||||
|
|
||||||
== Changelog
|
== Changelog
|
||||||
|
|
||||||
|
* *2.6*: The `sendfile` option was added.
|
||||||
* *2.5*: The `linger_timeout` option was added.
|
* *2.5*: The `linger_timeout` option was added.
|
||||||
* *2.2*: The `max_skip_body_length` option was added.
|
* *2.2*: The `max_skip_body_length` option was added.
|
||||||
* *2.0*: The `timeout` option was renamed `request_timeout`.
|
* *2.0*: The `timeout` option was renamed `request_timeout`.
|
||||||
|
|
|
@ -30,6 +30,7 @@ opts() :: #{
|
||||||
max_frame_size_sent => 16384..16777215 | infinity,
|
max_frame_size_sent => 16384..16777215 | infinity,
|
||||||
middlewares => [module()],
|
middlewares => [module()],
|
||||||
preface_timeout => timeout(),
|
preface_timeout => timeout(),
|
||||||
|
sendfile => boolean(),
|
||||||
settings_timeout => timeout(),
|
settings_timeout => timeout(),
|
||||||
shutdown_timeout => timeout(),
|
shutdown_timeout => timeout(),
|
||||||
stream_handlers => [module()]
|
stream_handlers => [module()]
|
||||||
|
@ -119,6 +120,12 @@ preface_timeout (5000)::
|
||||||
|
|
||||||
Time in ms Cowboy is willing to wait for the connection preface.
|
Time in ms Cowboy is willing to wait for the connection preface.
|
||||||
|
|
||||||
|
sendfile (true)::
|
||||||
|
|
||||||
|
Whether the sendfile syscall may be used. It can be useful to disable
|
||||||
|
it on systems where the syscall has a buggy implementation, for example
|
||||||
|
under VirtualBox when using shared folders.
|
||||||
|
|
||||||
settings_timeout (5000)::
|
settings_timeout (5000)::
|
||||||
|
|
||||||
Time in ms Cowboy is willing to wait for a SETTINGS ack.
|
Time in ms Cowboy is willing to wait for a SETTINGS ack.
|
||||||
|
@ -133,6 +140,7 @@ Ordered list of stream handlers that will handle all stream events.
|
||||||
|
|
||||||
== Changelog
|
== Changelog
|
||||||
|
|
||||||
|
* *2.6*: The `sendfile` option was added.
|
||||||
* *2.4*: Add the options `initial_connection_window_size`,
|
* *2.4*: Add the options `initial_connection_window_size`,
|
||||||
`initial_stream_window_size`, `max_concurrent_streams`,
|
`initial_stream_window_size`, `max_concurrent_streams`,
|
||||||
`max_decode_table_size`, `max_encode_table_size`,
|
`max_decode_table_size`, `max_encode_table_size`,
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
middlewares => [module()],
|
middlewares => [module()],
|
||||||
proxy_header => boolean(),
|
proxy_header => boolean(),
|
||||||
request_timeout => timeout(),
|
request_timeout => timeout(),
|
||||||
|
sendfile => boolean(),
|
||||||
shutdown_timeout => timeout(),
|
shutdown_timeout => timeout(),
|
||||||
stream_handlers => [module()],
|
stream_handlers => [module()],
|
||||||
tracer_callback => cowboy_tracer_h:tracer_callback(),
|
tracer_callback => cowboy_tracer_h:tracer_callback(),
|
||||||
|
@ -1050,7 +1051,7 @@ commands(State=#state{socket=Socket, transport=Transport, streams=Streams, out_s
|
||||||
end,
|
end,
|
||||||
commands(State#state{out_state=done}, StreamID, Tail);
|
commands(State#state{out_state=done}, StreamID, Tail);
|
||||||
%% Send a file.
|
%% Send a file.
|
||||||
commands(State0=#state{socket=Socket, transport=Transport}, StreamID,
|
commands(State0=#state{socket=Socket, transport=Transport, opts=Opts}, StreamID,
|
||||||
[{sendfile, IsFin, Offset, Bytes, Path}|Tail]) ->
|
[{sendfile, IsFin, Offset, Bytes, Path}|Tail]) ->
|
||||||
%% @todo exit with response_body_too_large if we exceed content-length
|
%% @todo exit with response_body_too_large if we exceed content-length
|
||||||
%% We wrap the sendfile call into a try/catch because on OTP-20
|
%% We wrap the sendfile call into a try/catch because on OTP-20
|
||||||
|
@ -1066,7 +1067,11 @@ commands(State0=#state{socket=Socket, transport=Transport}, StreamID,
|
||||||
%% This try/catch prevents some noisy logs to be written
|
%% This try/catch prevents some noisy logs to be written
|
||||||
%% when these errors occur.
|
%% when these errors occur.
|
||||||
try
|
try
|
||||||
Transport:sendfile(Socket, Path, Offset, Bytes),
|
%% When sendfile is disabled we explicitly use the fallback.
|
||||||
|
_ = case maps:get(sendfile, Opts, true) of
|
||||||
|
true -> Transport:sendfile(Socket, Path, Offset, Bytes);
|
||||||
|
false -> ranch_transport:sendfile(Transport, Socket, Path, Offset, Bytes, [])
|
||||||
|
end,
|
||||||
State = case IsFin of
|
State = case IsFin of
|
||||||
fin -> State0#state{out_state=done}
|
fin -> State0#state{out_state=done}
|
||||||
%% @todo Add the sendfile command.
|
%% @todo Add the sendfile command.
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
middlewares => [module()],
|
middlewares => [module()],
|
||||||
preface_timeout => timeout(),
|
preface_timeout => timeout(),
|
||||||
proxy_header => boolean(),
|
proxy_header => boolean(),
|
||||||
|
sendfile => boolean(),
|
||||||
settings_timeout => timeout(),
|
settings_timeout => timeout(),
|
||||||
shutdown_timeout => timeout(),
|
shutdown_timeout => timeout(),
|
||||||
stream_handlers => [module()],
|
stream_handlers => [module()],
|
||||||
|
@ -650,10 +651,14 @@ send_data_frame(State=#state{socket=Socket, transport=Transport},
|
||||||
StreamID, IsFin, {data, Data}) ->
|
StreamID, IsFin, {data, Data}) ->
|
||||||
Transport:send(Socket, cow_http2:data(StreamID, IsFin, Data)),
|
Transport:send(Socket, cow_http2:data(StreamID, IsFin, Data)),
|
||||||
State;
|
State;
|
||||||
send_data_frame(State=#state{socket=Socket, transport=Transport},
|
send_data_frame(State=#state{socket=Socket, transport=Transport, opts=Opts},
|
||||||
StreamID, IsFin, {sendfile, Offset, Bytes, Path}) ->
|
StreamID, IsFin, {sendfile, Offset, Bytes, Path}) ->
|
||||||
Transport:send(Socket, cow_http2:data_header(StreamID, IsFin, Bytes)),
|
Transport:send(Socket, cow_http2:data_header(StreamID, IsFin, Bytes)),
|
||||||
Transport:sendfile(Socket, Path, Offset, Bytes),
|
%% When sendfile is disabled we explicitly use the fallback.
|
||||||
|
_ = case maps:get(sendfile, Opts, true) of
|
||||||
|
true -> Transport:sendfile(Socket, Path, Offset, Bytes);
|
||||||
|
false -> ranch_transport:sendfile(Transport, Socket, Path, Offset, Bytes, [])
|
||||||
|
end,
|
||||||
State;
|
State;
|
||||||
%% The stream is terminated in cow_http2_machine:prepare_trailers.
|
%% The stream is terminated in cow_http2_machine:prepare_trailers.
|
||||||
send_data_frame(State=#state{socket=Socket, transport=Transport,
|
send_data_frame(State=#state{socket=Socket, transport=Transport,
|
||||||
|
|
|
@ -23,7 +23,10 @@
|
||||||
%% ct.
|
%% ct.
|
||||||
|
|
||||||
all() ->
|
all() ->
|
||||||
cowboy_test:common_all().
|
cowboy_test:common_all() ++ [
|
||||||
|
{group, http_no_sendfile},
|
||||||
|
{group, h2c_no_sendfile}
|
||||||
|
].
|
||||||
|
|
||||||
groups() ->
|
groups() ->
|
||||||
AllTests = ct_helper:all(?MODULE),
|
AllTests = ct_helper:all(?MODULE),
|
||||||
|
@ -44,7 +47,10 @@ groups() ->
|
||||||
{http_compress, [parallel], GroupTests},
|
{http_compress, [parallel], GroupTests},
|
||||||
{https_compress, [parallel], GroupTests},
|
{https_compress, [parallel], GroupTests},
|
||||||
{h2_compress, [parallel], GroupTests},
|
{h2_compress, [parallel], GroupTests},
|
||||||
{h2c_compress, [parallel], GroupTests}
|
{h2c_compress, [parallel], GroupTests},
|
||||||
|
%% No real need to test sendfile disabled against https or h2.
|
||||||
|
{http_no_sendfile, [parallel], GroupTests},
|
||||||
|
{h2c_no_sendfile, [parallel], GroupTests}
|
||||||
].
|
].
|
||||||
|
|
||||||
init_per_suite(Config) ->
|
init_per_suite(Config) ->
|
||||||
|
@ -94,8 +100,17 @@ init_per_group(dir, Config) ->
|
||||||
[{prefix, "/dir"}|Config];
|
[{prefix, "/dir"}|Config];
|
||||||
init_per_group(priv_dir, Config) ->
|
init_per_group(priv_dir, Config) ->
|
||||||
[{prefix, "/priv_dir"}|Config];
|
[{prefix, "/priv_dir"}|Config];
|
||||||
init_per_group(tttt, Config) ->
|
init_per_group(Name=http_no_sendfile, Config) ->
|
||||||
Config;
|
cowboy_test:init_http(Name, #{
|
||||||
|
env => #{dispatch => init_dispatch(Config)},
|
||||||
|
sendfile => false
|
||||||
|
}, [{flavor, vanilla}|Config]);
|
||||||
|
init_per_group(Name=h2c_no_sendfile, Config) ->
|
||||||
|
Config1 = cowboy_test:init_http(Name, #{
|
||||||
|
env => #{dispatch => init_dispatch(Config)},
|
||||||
|
sendfile => false
|
||||||
|
}, [{flavor, vanilla}|Config]),
|
||||||
|
lists:keyreplace(protocol, 1, Config1, {protocol, http2});
|
||||||
init_per_group(Name, Config) ->
|
init_per_group(Name, Config) ->
|
||||||
cowboy_test:init_common_groups(Name, Config, ?MODULE).
|
cowboy_test:init_common_groups(Name, Config, ?MODULE).
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue