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

Optimize cowboy_static:rest_init/2

This commit is contained in:
Loïc Hoguin 2013-02-27 23:20:55 +01:00
parent 87017e9699
commit 62e2635d8e

View file

@ -102,10 +102,10 @@
%% header is generated. %% header is generated.
%% %%
%% If a strong ETag is required a user defined function for generating the %% If a strong ETag is required a user defined function for generating the
%% header value can be supplied. The function must accept a proplist of the %% header value can be supplied. The function must accept a list of key/values
%% file attributes as the first argument and a second argument containing any %% of the file attributes as the first argument and a second argument
%% additional data that the function requires. The function must return a term %% containing any additional data that the function requires. The function
%% of the type `{weak | strong, binary()}' or `undefined'. %% must return a term of the type `{weak | strong, binary()}' or `undefined'.
%% %%
%% ==== Examples ==== %% ==== Examples ====
%% ``` %% ```
@ -202,7 +202,8 @@
fileinfo :: {ok, #file_info{}} | {error, _} | error, fileinfo :: {ok, #file_info{}} | {error, _} | error,
mimetypes :: {fun((binary(), T) -> [mimedef()]), T} | undefined, mimetypes :: {fun((binary(), T) -> [mimedef()]), T} | undefined,
etag_fun :: {fun(([etagarg()], T) -> etag_fun :: {fun(([etagarg()], T) ->
undefined | {strong | weak, binary()}), T}}). undefined | {strong | weak, binary()}), T}
}).
%% @private Upgrade from HTTP handler to REST handler. %% @private Upgrade from HTTP handler to REST handler.
init({_Transport, http}, _Req, _Opts) -> init({_Transport, http}, _Req, _Opts) ->
@ -211,37 +212,41 @@ init({_Transport, http}, _Req, _Opts) ->
%% @private Set up initial state of REST handler. %% @private Set up initial state of REST handler.
-spec rest_init(Req, list()) -> {ok, Req, #state{}} when Req::cowboy_req:req(). -spec rest_init(Req, list()) -> {ok, Req, #state{}} when Req::cowboy_req:req().
rest_init(Req, Opts) -> rest_init(Req, Opts) ->
Directory = proplists:get_value(directory, Opts), {_, DirectoryOpt} = lists:keyfind(directory, 1, Opts),
Directory1 = directory_path(Directory), Directory = directory_path(DirectoryOpt),
Mimetypes = proplists:get_value(mimetypes, Opts, []), case lists:keyfind(file, 1, Opts) of
Mimetypes1 = case Mimetypes of false ->
{{M, F}, E} -> {fun M:F/2, E}; {Filepath, Req2} = cowboy_req:path_info(Req),
{_, _} -> Mimetypes; case check_path(Filepath) of
[] -> {fun path_to_mimetypes/2, []}; ok ->
[_|_] -> {fun path_to_mimetypes/2, Mimetypes} Filepath2 = join_paths(Directory, Filepath),
rest_init(Req2, Opts, Filepath2);
error ->
{ok, Req2, #state{filepath=error, fileinfo=error,
mimetypes=undefined, etag_fun=undefined}}
end;
{_, FileOpt} ->
Filepath = join_paths(Directory, filepath_path(FileOpt)),
rest_init(Req, Opts, Filepath)
end.
rest_init(Req, Opts, Filepath) ->
Fileinfo = file:read_file_info(Filepath),
Mimetypes = case lists:keyfind(mimetypes, 1, Opts) of
false -> {fun path_to_mimetypes/2, []};
{_, {{M, F}, E}} -> {fun M:F/2, E};
{_, Mtypes} when is_tuple(Mtypes) -> Mtypes;
{_, Mtypes} when is_list(Mtypes) -> {fun path_to_mimetypes/2, Mtypes}
end, end,
ETagFunction = case proplists:get_value(etag, Opts) of EtagFun = case lists:keyfind(etag, 1, Opts) of
default -> {fun no_etag_function/2, undefined}; false -> {fun no_etag_function/2, undefined};
undefined -> {fun no_etag_function/2, undefined}; {_, default} -> {fun no_etag_function/2, undefined};
{attributes, []} -> {fun no_etag_function/2, undefined}; {_, {attributes, []}} -> {fun no_etag_function/2, undefined};
{attributes, Attrs} -> {fun attr_etag_function/2, Attrs}; {_, {attributes, Attrs}} -> {fun attr_etag_function/2, Attrs};
{_, _}=ETagFunction1 -> ETagFunction1 {_, EtagOpt} -> EtagOpt
end, end,
{Filepath, Req1} = case lists:keyfind(file, 1, Opts) of {ok, Req, #state{filepath=Filepath, fileinfo=Fileinfo,
{_, Filepath2} -> {filepath_path(Filepath2), Req}; mimetypes=Mimetypes, etag_fun=EtagFun}}.
false -> cowboy_req:path_info(Req)
end,
State = case check_path(Filepath) of
error ->
#state{filepath=error, fileinfo=error, mimetypes=undefined,
etag_fun=ETagFunction};
ok ->
Filepath1 = join_paths(Directory1, Filepath),
Fileinfo = file:read_file_info(Filepath1),
#state{filepath=Filepath1, fileinfo=Fileinfo, mimetypes=Mimetypes1,
etag_fun=ETagFunction}
end,
{ok, Req1, State}.
%% @private Only allow GET and HEAD requests on files. %% @private Only allow GET and HEAD requests on files.
-spec allowed_methods(Req, #state{}) -spec allowed_methods(Req, #state{})