Skip to content

Instantly share code, notes, and snippets.

@dmitriid
Created July 11, 2013 11:06
Show Gist options
  • Save dmitriid/5974555 to your computer and use it in GitHub Desktop.
Save dmitriid/5974555 to your computer and use it in GitHub Desktop.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% @doc site outputs secure http-only cookies. Because of that you
%%% cannot mix Selenium and inets in your tests
%%%
%%% Basically, when you find youself writing code like
%%% {ok, Cookie} = kselenium:cmd(getCookie, []),
%%% httpc:request(get, {Page, [{"Cookie", Cookie}]},[],[])
%%% this *will not work*. You must use inets.
%%%
%%% This lib ensures that cookies are recorded and sent out with each
%%% request and provides some additional utility functions
%%%
%%% @copyright 2012 Klarna AB
%%% @end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%_* Module declaration =======================================================
-module(inets_test_lib).
%%%_* Exports ==================================================================
%% HTTP
-export([ get/1
, post/2
]).
%% Returned state. Utilities
-export([ body/1
, cookie/1
, headers/1
, status/1
]).
% Misc utilities
-export([ parse_result/1
, proplist_to_query_string/1
]).
%%%_* Defines ==================================================================
-record(state, { body = []
, cookie = []
, headers = []
, status = 200
}).
-type state() :: #state{}.
%%%_* API =====================================================================
-spec post(Url::string(), Data::proplists:proplist()) ->
{ok, NewState::state()} | {error, Error::any()}.
post(Url, Data) ->
Result = do_post(Url, Data),
parse_result(Result).
-spec get(Url::string()) ->
{ok, NewState::state()} | {error, Error::any()}.
get(Url) ->
Result = do_get(Url),
parse_result(Result).
-spec cookie(state()) -> string().
cookie(#state{cookie = Cookie}) ->
Cookie.
-spec body(state()) -> string().
body(#state{body = Response}) ->
Response.
-spec status(state()) -> integer().
status(#state{status = Status}) ->
Status.
-spec headers(state()) -> string().
headers(#state{headers = Headers}) ->
Headers.
%%%_* Utilities=================================================================
%%
%% @doc Convert [{param1, value1}, {param2, value2}] to
%% "param1=value1&param2=value2"
%% Will url encode both params and values in the process
%%
-spec proplist_to_query_string(proplists:proplist()) -> string().
proplist_to_query_string(List0) ->
F = fun http_uri:encode/1,
List = [lists:flatten([F(Key), "=", F(Value)]) || {Key, Value} <- List0],
string:join(List, "&").
%%%_* Internal =================================================================
do_post(Url, Data) ->
httpc:set_options([{cookies, enabled}]),
httpc:request( post
, { Url
, [httpc:cookie_header(Url)]
, "application/x-www-form-urlencoded"
, proplist_to_query_string(Data)
}
, []
, []).
do_get(Url) ->
httpc:set_options([{cookies, enabled}]),
httpc:request( get
, { Url
, [httpc:cookie_header(Url)]
}
, []
, []).
parse_result({error, _} = Error) ->
Error;
parse_result({ok, {Status, Headers, Body}}) ->
Cookie = get_cookie_from_headers(Headers),
{ok, #state{ cookie = Cookie
, headers = Headers
, body = Body
, status = Status
}
}.
%%%_* Helpers ==================================================================
get_cookie_from_headers(List) ->
proplists:get_value("set-cookie", List, "").
%%%_* Emacs ====================================================================
%%% Local Variables:
%%% allout-layout: t
%%% erlang-indent-level: 2
%%% End:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment