Current section

Files

Jump to
launchdarkly_server_sdk src ldclient_update_requestor_httpc.erl
Raw

src/ldclient_update_requestor_httpc.erl

%%-------------------------------------------------------------------
%% @doc Polling update requestor
%%
%% @end
%%-------------------------------------------------------------------
-module(ldclient_update_requestor_httpc).
-behaviour(ldclient_update_requestor).
%% Behavior callbacks
-export([init/0, all/3]).
%% Internal type for ETag cache state
-type state() :: #{string() => binary()}.
%%===================================================================
%% Behavior callbacks
%%===================================================================
%% Initializes ETag cache to empty map
-spec init() -> state().
init() -> #{}.
%% @doc Send events to LaunchDarkly event server
%%
%% @end
-spec all(Uri :: string(), SdkKey :: string(), State :: state()) ->
{ldclient_update_requestor:response(), state()}.
all(Uri, SdkKey, State) ->
Headers = [
{"Authorization", SdkKey},
{"X-LaunchDarkly-Event-Schema", ldclient_settings:get_event_schema()},
{"User-Agent", ldclient_settings:get_user_agent()}
],
ETagHeaders = case maps:find(Uri, State) of
error -> Headers;
{ok, Etag} -> [{"If-None-Match", Etag}|Headers]
end,
HTTPOptions = [{connect_timeout, 2000}],
Result = httpc:request(get, {Uri, ETagHeaders}, HTTPOptions, [{body_format, binary}]),
case Result of
{ok, {StatusLine = {_, StatusCode, _}, ResponseHeaders, Body}} ->
if
StatusCode =:= 304 -> {{ok, not_modified}, State};
StatusCode < 300 ->
case proplists:lookup("etag", [{string:casefold(K), V} || {K, V} <- ResponseHeaders]) of
none -> {{ok, Body}, State};
{_, ETag} -> {{ok, Body}, State#{Uri => ETag}}
end;
StatusCode < 400 -> {{ok, Body}, State};
true -> {{error, bad_status_error(StatusLine)}, State}
end;
_ -> {{error, network_error}, State}
end.
%%===================================================================
%% Internal functions
%%===================================================================
-spec bad_status_error(StatusLine :: httpc:status_line()) -> ldclient_update_requestor:errors().
bad_status_error({Version, StatusCode, ReasonPhrase}) ->
{bad_status, StatusCode, io_lib:format("~s ~b ~s", [Version, StatusCode, ReasonPhrase])}.