%% @author Marc Worrell <marc@worrell.nl>
%% @copyright 2010-2022 Marc Worrell
%% @doc Model for the accessing the HTTP request properties. Exposes Cowmachine's wrq.erl
%% Copyright 2010-2022 Marc Worrell
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
-module(m_req).
-author("Marc Worrell <marc@worrell.nl").
-behaviour(zotonic_model).
%% interface functions
-export([
m_get/3,
get/2
]).
-include_lib("zotonic.hrl").
%% @doc Fetch the value for the key from a model source
-spec m_get( list(), zotonic_model:opt_msg(), z:context() ) -> zotonic_model:return().
m_get([ Key | Rest ], _Msg, Context) when is_binary(Key) ->
try
KeyAtom = erlang:binary_to_existing_atom(Key, utf8),
{ok, {get(KeyAtom, Context), Rest}}
catch
error:badarg ->
{error, unknown_key}
end;
m_get([], _Msg, Context) ->
{ok, {values(Context), []}};
m_get(_Vs, _Msg, _Context) ->
{error, unknown_path}.
%% @doc Fetch the field from the cowmachine_req interface.
-spec get(atom(), z:context() | cowboy_req:req() | undefined) -> any().
get(undefined, _) -> undefined;
get(_, undefined) -> undefined;
get(site, #context{} = Context) -> z_context:site(Context);
get(timezone, #context{} = Context) -> z_context:tz(Context);
get(language, #context{} = Context) -> z_context:language(Context);
get(csp_nonce, Context) -> z_context:csp_nonce(Context);
get(is_crawler, #context{} = Context) -> z_user_agent:is_crawler(Context);
get(peer_ip, #context{} = Context) ->
case z_context:get(peer_ip, Context) of
undefined -> get_req(peer_ip, Context);
PeerIP -> PeerIP
end;
get(What, #context{} = Context) ->
case z_context:is_request(Context) of
true -> get_req(What, Context);
false -> undefined
end.
-spec get_req( atom(), z:context() ) -> any().
get_req(method, Context) -> cowmachine_req:method(Context);
get_req(version, Context) -> cowmachine_req:version(Context);
get_req(peer, Context) -> cowmachine_req:peer(Context);
get_req(peer_ip, Context) -> cowmachine_req:peer_ip(Context);
get_req(is_ssl, Context) -> cowmachine_req:is_ssl(Context);
get_req(scheme, Context) -> cowmachine_req:scheme(Context);
get_req(host, Context) -> cowmachine_req:host(Context);
get_req(port, Context) ->
case cowmachine_req:is_proxy(Context) of
true -> cowmachine_req:port(Context);
false ->
case cowmachine_req:is_ssl(Context) of
true -> z_config:get(ssl_port);
false -> z_config:get(port)
end
end;
get_req(raw_path, Context) -> cowmachine_req:raw_path(Context);
get_req(path, Context) -> cowmachine_req:path(Context);
get_req(qs, Context) -> cowmachine_req:req_qs(Context);
get_req(headers, Context) -> cowmachine_req:get_req_headers(Context);
get_req(user_agent, Context) -> cowmachine_req:get_req_header(<<"user-agent">>, Context);
get_req(referer, Context) -> cowmachine_req:get_req_header(<<"referer">>, Context);
get_req(referrer, Context) -> get_req(referer, Context);
get_req(_Key, _Context) -> undefined.
-spec values( z:context() ) -> list({atom(), any()}).
values(Context) ->
[ {K, get(K, Context)} || K <- [
method, version, peer, is_ssl, host, port, raw_path, path, qs, referrer, user_agent, is_crawler,
headers, timezone, language
]
].