anchor.diff:  -module(simple_http_worker).
   
   -export([initial_state/0, metrics/0,
  -         get/3, get/4, post/5, random_get/3]).
  +         get/3, get/4, post/5, random_get/3, reset_cookies/2]).
   
   -type state() :: term().
   -type meta() :: [{Key :: atom(), Value :: any()}].
  
positive.code:     ShouldLog = proplists:get_value(log, Options, false),
      ExpectedCode = proplists:get_value(expected, Options, 200),
  
      ShouldLog andalso lager:info("POST ~s", [URL]),
  
      {HackneyOptions, Headers} = parse_options(Options),
      StartTime = os:timestamp(),
      Response = hackney:request(post, list_to_binary(URL), Headers, list_to_binary(Body), HackneyOptions),
      Latency = timer:now_diff(os:timestamp(), StartTime),
  
      mzb_metrics:notify({"latency", histogram}, Latency),
  
      case Response of
          {ok, ExpectedCode, _, Ref} ->
              hackney:skip_body(Ref),
              mzb_metrics:notify({"http_ok", counter}, 1);
          {ok, _, _, Ref} = Reply ->
              lager:error("POST failed~nURL: ~p~nHeaders: ~p~nBody: ~p~nReply:~p~n~p", [URL, Headers, Body, Reply, hackney:body(Ref)]),
              mzb_metrics:notify({"http_fail", counter}, 1);
          E ->
              lager:error("hackney:request failed~nURL: ~p~nHeaders: ~p~nBody: ~p~nReason: ~p", [URL, Headers, Body, E]),
              mzb_metrics:notify({"other_fail", counter}, 1)
      end,
  
      {nil, State}.
  
  random_get(State, Meta, List) ->
  
negative.code: parse_options([_|T], OAcc, HAcc) ->
      parse_options(T, OAcc, HAcc).
  
  add_cookies(Headers) ->
      case get(simple_http_cookies) of
          undefined -> Headers;
          <<"">> -> Headers;
          C -> [{<<"Cookie">>, C}] ++ Headers
      end.
  
  save_cookies(Headers) ->
      case proplists:get_all_values(<<"Set-Cookie">>, Headers) of
          [] -> ok;
          SetCookies ->
              OldCookies =
                  case get(simple_http_cookies) of
                      undefined -> <<"">>;
                      C -> C
                  end,
  
              Old = parse_cookies(OldCookies),
              New = parse_set_cookies(SetCookies),
              Merged = New ++ [{K, V} || {K, V} <- Old,
                                undefined == proplists:get_value(K, New)],
              Joined = string:join([K++"="++V || {K, V} <- Merged], ";"),
              put(simple_http_cookies, list_to_binary(Joined))
      end.
  
  parse_set_cookies(Cookies) ->
      lists:map(
          fun (Cookie) ->
              [KeyValue|_] = string:tokens(binary_to_list(Cookie), ";"),
              Index = string:chr(KeyValue, $=),
              Key = string:sub_string(KeyValue, 1, Index - 1),
              Value = string:sub_string(KeyValue, Index + 1),
              {Key, Value}
          end, Cookies).
  
  parse_cookies(Cookies) ->
      lists:map(
          fun (KeyValue) ->
              Index = string:chr(KeyValue, $=),
              Key = string:sub_string(KeyValue, 1, Index - 1),
              Value = string:sub_string(KeyValue, Index + 1),
              {Key, Value}
          end, string:tokens(binary_to_list(Cookies), ";")).
  