/ucengine/src/core/uce_appmod.erl
Erlang | 135 lines | 103 code | 8 blank | 24 comment | 0 complexity | 4a87ba5687c7dee823e1020f5b2f0ca1 MD5 | raw file
- %%
- %% U.C.Engine - Unified Collaboration Engine
- %% Copyright (C) 2011 af83
- %%
- %% This program is free software: you can redistribute it and/or modify
- %% it under the terms of the GNU Affero General Public License as published by
- %% the Free Software Foundation, either version 3 of the License, or
- %% (at your option) any later version.
- %%
- %% This program is distributed in the hope that it will be useful,
- %% but WITHOUT ANY WARRANTY; without even the implied warranty of
- %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- %% GNU Affero General Public License for more details.
- %%
- %% You should have received a copy of the GNU Affero General Public License
- %% along with this program. If not, see <http://www.gnu.org/licenses/>.
- %%
- -module(uce_appmod).
- -include("uce.hrl").
- -include_lib("yaws/include/yaws_api.hrl").
- -export([out/1]).
- convert2(string, Value) ->
- Value;
- convert2(integer, Value) when is_integer(Value) ->
- Value;
- convert2(integer, Value) ->
- case string:to_integer(Value) of
- {error, _} ->
- {error, bad_parameters};
- {Integer, _} ->
- Integer
- end;
- convert2(atom, Value) when is_atom(Value) ->
- Value;
- convert2(atom, Value) ->
- list_to_atom(Value);
- convert2(dictionary, Value) ->
- Value;
- convert2(file, Value) when is_record(Value, file_upload) ->
- Value;
- convert2(file, _Value) ->
- {error, bad_parameters}.
- convert(Param, Type)
- when is_atom(Type) ->
- convert(Param, [Type]);
- convert(_, []) ->
- throw({error, bad_parameters});
- convert(Param, [Type|Tail]) ->
- Result = convert2(Type, Param),
- case Result of
- {error, _} ->
- convert(Param, Tail);
- _ ->
- Result
- end.
- validate(_, []) ->
- [];
- validate(Query, [{Name, Default, Types}|ParamsSpecList]) ->
- case utils:get(Query, [Name], [Default]) of
- [required] ->
- throw({error, missing_parameters, lists:flatten(io_lib:format("Parameter '~s' is missing", [Name]))});
- [RawValue] ->
- [convert(RawValue, Types)] ++ validate(Query, ParamsSpecList)
- end.
- call_handlers(Domain, {Module, Function, ParamsSpecList}, Query, Match, Arg) ->
- case catch validate(Query, ParamsSpecList) of
- {error, Reason} ->
- json_helpers:error(Domain, Reason);
- {error, Reason, Infos} ->
- ?ERROR_MSG("~p: error: ~p:~p: ~p ~p~n", [Domain, Module, Function, Reason, Infos]),
- json_helpers:error(Domain, Reason, Infos);
- Params ->
- ?DEBUG("~p: call ~p:~p matching ~p with ~p~n", [Domain, Module, Function, Match, Params]),
- Now = now(),
- try Module:Function(Domain, Match, Params, Arg) of
- {streamcontent_with_timeout, _, _, _} = Stream ->
- cors_helpers:format_cors_headers(Domain) ++ [Stream];
- Response when is_list(Response) ->
- ?TIMER_APPEND(atom_to_list(Module) ++ "_" ++ atom_to_list(Function), Now),
- Response
- catch
- {error, Reason} ->
- ?ERROR_MSG("~p: error: ~p:~p: ~p ~p~n", [Domain, Module, Function, Reason, Params]),
- json_helpers:error(Domain, Reason);
- E ->
- ?ERROR_MSG("~p: error: ~p:~p: ~p ~p~n", [Domain, Module, Function, Params, E]),
- json_helpers:unexpected_error(Domain)
- end
- end.
- %%
- %% Function called by yaws
- %% For each vhost we support, we store to the opaque field the current domain
- %%
- out(#arg{} = Arg) ->
- ?COUNTER('http:request'),
- Host = Arg#arg.opaque,
- case uce_http:parse(Host, Arg) of
- {error, Reason} ->
- json_helpers:error(Host, Reason);
- {get_more, _, _} = State ->
- State;
- {Method, Path, Query} ->
- process(Host, Method, Path, Query, Arg)
- end.
- % Handle options method. If one route match, return ok
- process(Host, 'OPTIONS', Path, _Query, _Arg) ->
- case routes:get(Path) of
- {ok, _Match, _Handlers} ->
- json_helpers:ok(Host);
- {error, not_found} ->
- ?ERROR_MSG("options ~p: no route found", [Path]),
- json_helpers:error(Host, not_found)
- end;
- % Handle head method. If a 'GET' route match, normal process
- % Yaws will strip the content
- process(Host, 'HEAD', Path, Query, Arg) ->
- process(Host, 'GET', Path, Query, Arg);
- process(Host, Method, Path, Query, Arg) ->
- ContentType = Arg#arg.headers#headers.content_type,
- case routes:get(Method, Path, ContentType) of
- {ok, Match, Handlers} ->
- call_handlers(Host, Handlers, Query, Match, Arg);
- {error, not_found} ->
- Description = lists:flatten(io_lib:format("~s on ~s did not match any route.", [Method, Path])),
- ?ERROR_MSG(Description, []),
- json_helpers:error(Host, not_found, Description)
- end.