PageRenderTime 41ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/ucengine/src/core/uce_appmod.erl

http://github.com/AF83/ucengine
Erlang | 135 lines | 103 code | 8 blank | 24 comment | 0 complexity | 4a87ba5687c7dee823e1020f5b2f0ca1 MD5 | raw file
  1. %%
  2. %% U.C.Engine - Unified Collaboration Engine
  3. %% Copyright (C) 2011 af83
  4. %%
  5. %% This program is free software: you can redistribute it and/or modify
  6. %% it under the terms of the GNU Affero General Public License as published by
  7. %% the Free Software Foundation, either version 3 of the License, or
  8. %% (at your option) any later version.
  9. %%
  10. %% This program is distributed in the hope that it will be useful,
  11. %% but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. %% GNU Affero General Public License for more details.
  14. %%
  15. %% You should have received a copy of the GNU Affero General Public License
  16. %% along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. %%
  18. -module(uce_appmod).
  19. -include("uce.hrl").
  20. -include_lib("yaws/include/yaws_api.hrl").
  21. -export([out/1]).
  22. convert2(string, Value) ->
  23. Value;
  24. convert2(integer, Value) when is_integer(Value) ->
  25. Value;
  26. convert2(integer, Value) ->
  27. case string:to_integer(Value) of
  28. {error, _} ->
  29. {error, bad_parameters};
  30. {Integer, _} ->
  31. Integer
  32. end;
  33. convert2(atom, Value) when is_atom(Value) ->
  34. Value;
  35. convert2(atom, Value) ->
  36. list_to_atom(Value);
  37. convert2(dictionary, Value) ->
  38. Value;
  39. convert2(file, Value) when is_record(Value, file_upload) ->
  40. Value;
  41. convert2(file, _Value) ->
  42. {error, bad_parameters}.
  43. convert(Param, Type)
  44. when is_atom(Type) ->
  45. convert(Param, [Type]);
  46. convert(_, []) ->
  47. throw({error, bad_parameters});
  48. convert(Param, [Type|Tail]) ->
  49. Result = convert2(Type, Param),
  50. case Result of
  51. {error, _} ->
  52. convert(Param, Tail);
  53. _ ->
  54. Result
  55. end.
  56. validate(_, []) ->
  57. [];
  58. validate(Query, [{Name, Default, Types}|ParamsSpecList]) ->
  59. case utils:get(Query, [Name], [Default]) of
  60. [required] ->
  61. throw({error, missing_parameters, lists:flatten(io_lib:format("Parameter '~s' is missing", [Name]))});
  62. [RawValue] ->
  63. [convert(RawValue, Types)] ++ validate(Query, ParamsSpecList)
  64. end.
  65. call_handlers(Domain, {Module, Function, ParamsSpecList}, Query, Match, Arg) ->
  66. case catch validate(Query, ParamsSpecList) of
  67. {error, Reason} ->
  68. json_helpers:error(Domain, Reason);
  69. {error, Reason, Infos} ->
  70. ?ERROR_MSG("~p: error: ~p:~p: ~p ~p~n", [Domain, Module, Function, Reason, Infos]),
  71. json_helpers:error(Domain, Reason, Infos);
  72. Params ->
  73. ?DEBUG("~p: call ~p:~p matching ~p with ~p~n", [Domain, Module, Function, Match, Params]),
  74. Now = now(),
  75. try Module:Function(Domain, Match, Params, Arg) of
  76. {streamcontent_with_timeout, _, _, _} = Stream ->
  77. cors_helpers:format_cors_headers(Domain) ++ [Stream];
  78. Response when is_list(Response) ->
  79. ?TIMER_APPEND(atom_to_list(Module) ++ "_" ++ atom_to_list(Function), Now),
  80. Response
  81. catch
  82. {error, Reason} ->
  83. ?ERROR_MSG("~p: error: ~p:~p: ~p ~p~n", [Domain, Module, Function, Reason, Params]),
  84. json_helpers:error(Domain, Reason);
  85. E ->
  86. ?ERROR_MSG("~p: error: ~p:~p: ~p ~p~n", [Domain, Module, Function, Params, E]),
  87. json_helpers:unexpected_error(Domain)
  88. end
  89. end.
  90. %%
  91. %% Function called by yaws
  92. %% For each vhost we support, we store to the opaque field the current domain
  93. %%
  94. out(#arg{} = Arg) ->
  95. ?COUNTER('http:request'),
  96. Host = Arg#arg.opaque,
  97. case uce_http:parse(Host, Arg) of
  98. {error, Reason} ->
  99. json_helpers:error(Host, Reason);
  100. {get_more, _, _} = State ->
  101. State;
  102. {Method, Path, Query} ->
  103. process(Host, Method, Path, Query, Arg)
  104. end.
  105. % Handle options method. If one route match, return ok
  106. process(Host, 'OPTIONS', Path, _Query, _Arg) ->
  107. case routes:get(Path) of
  108. {ok, _Match, _Handlers} ->
  109. json_helpers:ok(Host);
  110. {error, not_found} ->
  111. ?ERROR_MSG("options ~p: no route found", [Path]),
  112. json_helpers:error(Host, not_found)
  113. end;
  114. % Handle head method. If a 'GET' route match, normal process
  115. % Yaws will strip the content
  116. process(Host, 'HEAD', Path, Query, Arg) ->
  117. process(Host, 'GET', Path, Query, Arg);
  118. process(Host, Method, Path, Query, Arg) ->
  119. ContentType = Arg#arg.headers#headers.content_type,
  120. case routes:get(Method, Path, ContentType) of
  121. {ok, Match, Handlers} ->
  122. call_handlers(Host, Handlers, Query, Match, Arg);
  123. {error, not_found} ->
  124. Description = lists:flatten(io_lib:format("~s on ~s did not match any route.", [Method, Path])),
  125. ?ERROR_MSG(Description, []),
  126. json_helpers:error(Host, not_found, Description)
  127. end.