0
Fork 0
mirror of https://github.com/ninenines/cowboy.git synced 2025-07-14 12:20:24 +00:00

Add sendfile support to SPDY, enabling cowboy_static use

This commit is contained in:
Loïc Hoguin 2013-06-03 19:10:03 +02:00
parent e50f7e4086
commit 1fc69977da
2 changed files with 48 additions and 4 deletions

View file

@ -42,6 +42,7 @@
%% Internal transport functions.
-export([name/0]).
-export([send/2]).
-export([sendfile/2]).
-record(child, {
streamid :: non_neg_integer(),
@ -174,6 +175,14 @@ loop(State=#state{parent=Parent, socket=Socket, transport=Transport,
Children2 = lists:keyreplace(StreamID,
#child.streamid, Children, Child#child{output=fin}),
loop(State#state{children=Children2});
{sendfile, {Pid, StreamID}, Filepath}
when Pid =:= self() ->
Child = #child{output=nofin} = lists:keyfind(StreamID,
#child.streamid, Children),
data_from_file(State, StreamID, Filepath),
Children2 = lists:keyreplace(StreamID,
#child.streamid, Children, Child#child{output=fin}),
loop(State#state{children=Children2});
{'EXIT', Parent, Reason} ->
exit(Reason);
{'EXIT', Pid, _} ->
@ -430,6 +439,27 @@ data(#state{socket=Socket, transport=Transport}, IsFin, StreamID, Data) ->
<< 0:1, StreamID:31, Flags:8, Len:24 >>,
Data]).
data_from_file(#state{socket=Socket, transport=Transport},
StreamID, Filepath) ->
{ok, IoDevice} = file:open(Filepath, [read, binary, raw]),
data_from_file(Socket, Transport, StreamID, IoDevice).
data_from_file(Socket, Transport, StreamID, IoDevice) ->
case file:read(IoDevice, 16#1fff) of
eof ->
_ = Transport:send(Socket, << 0:1, StreamID:31, 1:8, 0:24 >>),
ok;
{ok, Data} ->
Len = byte_size(Data),
Data2 = [<< 0:1, StreamID:31, 0:8, Len:24 >>, Data],
case Transport:send(Socket, Data2) of
ok ->
data_from_file(Socket, Transport, StreamID, IoDevice);
{error, _} ->
ok
end
end.
%% Request process.
request_init(Parent, StreamID, Peer,
@ -535,10 +565,16 @@ stream_close(Socket = {Pid, _}) ->
ok.
%% Internal transport functions.
%% @todo recv, sendfile
%% @todo recv
name() ->
spdy.
send(Socket, Data) ->
stream_data(Socket, Data).
%% We don't wait for the result of the actual sendfile call,
%% therefore we can't know how much was actually sent.
sendfile(Socket = {Pid, _}, Filepath) ->
_ = Pid ! {sendfile, Socket, Filepath},
{ok, undefined}.

View file

@ -44,9 +44,13 @@ init_per_suite(Config) ->
application:start(cowboy),
application:start(public_key),
application:start(ssl),
Config.
Dir = ?config(priv_dir, Config) ++ "/static",
ct_helper:create_static_dir(Dir),
[{static_dir, Dir}|Config].
end_per_suite(_Config) ->
end_per_suite(Config) ->
Dir = ?config(static_dir, Config),
ct_helper:delete_static_dir(Dir),
application:stop(ssl),
application:stop(public_key),
application:stop(cowboy),
@ -69,9 +73,12 @@ end_per_group(Name, _) ->
%% Dispatch configuration.
init_dispatch(_) ->
init_dispatch(Config) ->
cowboy_router:compile([
{"localhost", [
{"/static/[...]", cowboy_static,
[{directory, ?config(static_dir, Config)},
{mimetypes, [{<<".css">>, [<<"text/css">>]}]}]},
{"/chunked", http_chunked, []},
{"/", http_handler, []}
]}
@ -152,6 +159,7 @@ check_status(Config) ->
Tests = [
{200, nofin, "localhost", "/"},
{200, nofin, "localhost", "/chunked"},
{200, nofin, "localhost", "/static/style.css"},
{400, fin, "bad-host", "/"},
{400, fin, "localhost", "bad-path"},
{404, fin, "localhost", "/this/path/does/not/exist"}