mirror of
https://github.com/ninenines/cowboy.git
synced 2025-07-14 20:30:23 +00:00
Add sendfile support to SPDY, enabling cowboy_static use
This commit is contained in:
parent
e50f7e4086
commit
1fc69977da
2 changed files with 48 additions and 4 deletions
|
@ -42,6 +42,7 @@
|
||||||
%% Internal transport functions.
|
%% Internal transport functions.
|
||||||
-export([name/0]).
|
-export([name/0]).
|
||||||
-export([send/2]).
|
-export([send/2]).
|
||||||
|
-export([sendfile/2]).
|
||||||
|
|
||||||
-record(child, {
|
-record(child, {
|
||||||
streamid :: non_neg_integer(),
|
streamid :: non_neg_integer(),
|
||||||
|
@ -174,6 +175,14 @@ loop(State=#state{parent=Parent, socket=Socket, transport=Transport,
|
||||||
Children2 = lists:keyreplace(StreamID,
|
Children2 = lists:keyreplace(StreamID,
|
||||||
#child.streamid, Children, Child#child{output=fin}),
|
#child.streamid, Children, Child#child{output=fin}),
|
||||||
loop(State#state{children=Children2});
|
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', Parent, Reason} ->
|
||||||
exit(Reason);
|
exit(Reason);
|
||||||
{'EXIT', Pid, _} ->
|
{'EXIT', Pid, _} ->
|
||||||
|
@ -430,6 +439,27 @@ data(#state{socket=Socket, transport=Transport}, IsFin, StreamID, Data) ->
|
||||||
<< 0:1, StreamID:31, Flags:8, Len:24 >>,
|
<< 0:1, StreamID:31, Flags:8, Len:24 >>,
|
||||||
Data]).
|
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 process.
|
||||||
|
|
||||||
request_init(Parent, StreamID, Peer,
|
request_init(Parent, StreamID, Peer,
|
||||||
|
@ -535,10 +565,16 @@ stream_close(Socket = {Pid, _}) ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
%% Internal transport functions.
|
%% Internal transport functions.
|
||||||
%% @todo recv, sendfile
|
%% @todo recv
|
||||||
|
|
||||||
name() ->
|
name() ->
|
||||||
spdy.
|
spdy.
|
||||||
|
|
||||||
send(Socket, Data) ->
|
send(Socket, Data) ->
|
||||||
stream_data(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}.
|
||||||
|
|
|
@ -44,9 +44,13 @@ init_per_suite(Config) ->
|
||||||
application:start(cowboy),
|
application:start(cowboy),
|
||||||
application:start(public_key),
|
application:start(public_key),
|
||||||
application:start(ssl),
|
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(ssl),
|
||||||
application:stop(public_key),
|
application:stop(public_key),
|
||||||
application:stop(cowboy),
|
application:stop(cowboy),
|
||||||
|
@ -69,9 +73,12 @@ end_per_group(Name, _) ->
|
||||||
|
|
||||||
%% Dispatch configuration.
|
%% Dispatch configuration.
|
||||||
|
|
||||||
init_dispatch(_) ->
|
init_dispatch(Config) ->
|
||||||
cowboy_router:compile([
|
cowboy_router:compile([
|
||||||
{"localhost", [
|
{"localhost", [
|
||||||
|
{"/static/[...]", cowboy_static,
|
||||||
|
[{directory, ?config(static_dir, Config)},
|
||||||
|
{mimetypes, [{<<".css">>, [<<"text/css">>]}]}]},
|
||||||
{"/chunked", http_chunked, []},
|
{"/chunked", http_chunked, []},
|
||||||
{"/", http_handler, []}
|
{"/", http_handler, []}
|
||||||
]}
|
]}
|
||||||
|
@ -152,6 +159,7 @@ check_status(Config) ->
|
||||||
Tests = [
|
Tests = [
|
||||||
{200, nofin, "localhost", "/"},
|
{200, nofin, "localhost", "/"},
|
||||||
{200, nofin, "localhost", "/chunked"},
|
{200, nofin, "localhost", "/chunked"},
|
||||||
|
{200, nofin, "localhost", "/static/style.css"},
|
||||||
{400, fin, "bad-host", "/"},
|
{400, fin, "bad-host", "/"},
|
||||||
{400, fin, "localhost", "bad-path"},
|
{400, fin, "localhost", "bad-path"},
|
||||||
{404, fin, "localhost", "/this/path/does/not/exist"}
|
{404, fin, "localhost", "/this/path/does/not/exist"}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue