Packages
launchdarkly_server_sdk
2.1.2
3.11.0
3.10.1
3.9.0
3.8.1
3.8.0
3.7.2
3.7.1
3.7.0
3.6.0
3.5.0
3.4.0
3.3.1
3.3.0
3.2.0
3.1.0
3.0.4
3.0.3
3.0.2
3.0.1
3.0.0
2.1.2
2.1.1
2.1.0
2.0.5
2.0.4
2.0.3
2.0.2
2.0.1
2.0.0
1.6.0
1.5.0
1.4.0
1.3.2
1.3.1
1.3.0
1.2.0
1.1.3
1.1.2
1.1.1
retired
1.1.0
retired
1.0.1
retired
1.0.0
retired
1.0.0-beta4
retired
1.0.0-beta3
retired
1.0.0-beta2
retired
LaunchDarkly SDK for Erlang
Current section
Files
Jump to
Current section
Files
src/ldclient_update_requestor_httpc.erl
%%-------------------------------------------------------------------
%% @doc Polling update requestor
%% @private
%% @end
%%-------------------------------------------------------------------
-module(ldclient_update_requestor_httpc).
-behaviour(ldclient_update_requestor).
%% Behavior callbacks
-export([init/2, all/2]).
%% Internal type for ETag cache state
-type state() :: #{
etag_state => #{string() => binary()},
headers => list(),
http_options => list()
}.
%%===================================================================
%% Behavior callbacks
%%===================================================================
-spec init(Tag :: atom(), SdkKey :: string()) -> state().
init(Tag, _SdkKey) ->
Options = ldclient_config:get_value(Tag, http_options),
HttpOptions = ldclient_http_options:httpc_parse_http_options(Options),
DefaultHeaders = ldclient_headers:get_default_headers(Tag, string_pairs),
Headers = ldclient_http_options:httpc_append_custom_headers([
{"X-LaunchDarkly-Event-Schema", ldclient_config:get_event_schema()}
| DefaultHeaders
], Options),
#{
%% Initializes ETag cache to empty map
etag_state => #{},
headers => Headers,
http_options => HttpOptions
}.
%% @doc Send events to LaunchDarkly event server
%%
%% @end
-spec all(Uri :: string(), State :: state()) ->
{ldclient_update_requestor:response(), state()}.
all(Uri, State) ->
#{etag_state := EtagState, headers := Headers, http_options := HttpOptions} = State,
ETagHeaders = case maps:find(Uri, EtagState) of
error -> Headers;
{ok, Etag} -> [{"If-None-Match", Etag}|Headers]
end,
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#{etag_state => EtagState#{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 :: {
uri_string:uri_string(),
non_neg_integer(),
string()
}) -> ldclient_update_requestor:errors().
bad_status_error({Version, StatusCode, ReasonPhrase}) ->
{bad_status, StatusCode, io_lib:format("~s ~b ~s", [Version, StatusCode, ReasonPhrase])}.