Skip to content

Commit

Permalink
Merge pull request erlcloud#117 from esl/sns-https-support
Browse files Browse the repository at this point in the history
HTTPS support for erlcloud_sns
  • Loading branch information
Ransom Richardson committed Oct 2, 2014
2 parents 71a7f74 + e8a6fdf commit 573cce3
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 9 deletions.
1 change: 1 addition & 0 deletions include/erlcloud_aws.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
elb_host="elasticloadbalancing.amazonaws.com"::string(),
ses_host="email.us-east-1.amazonaws.com"::string(),
sqs_host="queue.amazonaws.com"::string(),
sns_scheme="http://"::string(),
sns_host="sns.amazonaws.com"::string(),
mturk_host="mechanicalturk.amazonaws.com"::string(),
mon_host="monitoring.amazonaws.com"::string(),
Expand Down
28 changes: 19 additions & 9 deletions src/erlcloud_sns.erl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
create_platform_endpoint/2, create_platform_endpoint/3,
create_platform_endpoint/4, create_platform_endpoint/5,
create_platform_endpoint/6,
create_topic/1, create_topic/2,
create_topic/1, create_topic/2,
delete_endpoint/1, delete_endpoint/2, delete_endpoint/3,
delete_topic/1, delete_topic/2,
list_endpoints_by_platform_application/1,
Expand Down Expand Up @@ -144,7 +144,7 @@ create_platform_endpoint(PlatformApplicationArn, Token, CustomUserData, Attribut
create_topic(TopicName) ->
create_topic(TopicName, default_config()).

create_topic(TopicName, Config)
create_topic(TopicName, Config)
when is_record(Config, aws_config) ->
Doc = sns_xml_request(Config, "CreateTopic", [{"Name", TopicName}]),
erlcloud_xml:get_text("/CreateTopicResponse/CreateTopicResult/TopicArn", Doc).
Expand Down Expand Up @@ -204,7 +204,7 @@ delete_endpoint(EndpointArn, AccessKeyID, SecretAccessKey) ->
delete_topic(TopicArn) ->
delete_topic(TopicArn, default_config()).

delete_topic(TopicArn, Config)
delete_topic(TopicArn, Config)
when is_record(Config, aws_config) ->
sns_simple_request(Config, "DeleteTopic", [{"TopicArn", TopicArn}]).

Expand Down Expand Up @@ -470,9 +470,10 @@ sns_simple_request(Config, Action, Params) ->

sns_xml_request(Config, Action, Params) ->
case erlcloud_aws:aws_request_xml2(
post, "http", Config#aws_config.sns_host, undefined, "/",
[{"Action", Action}, {"Version", ?API_VERSION} | Params],
Config) of
post, scheme_to_protocol(Config#aws_config.sns_scheme),
Config#aws_config.sns_host, undefined, "/",
[{"Action", Action}, {"Version", ?API_VERSION} | Params],
Config) of
{ok, XML} -> XML;
{error, {http_error, 400, _BadRequest, Body}} ->
XML = element(1, xmerl_scan:string(binary_to_list(Body))),
Expand All @@ -485,9 +486,10 @@ sns_xml_request(Config, Action, Params) ->

sns_request(Config, Action, Params) ->
case erlcloud_aws:aws_request2(
post, "http", Config#aws_config.sns_host, undefined, "/",
[{"Action", Action}, {"Version", ?API_VERSION} | Params],
Config) of
post, scheme_to_protocol(Config#aws_config.sns_scheme),
Config#aws_config.sns_host, undefined, "/",
[{"Action", Action}, {"Version", ?API_VERSION} | Params],
Config) of
{ok, _Response} -> ok;
{error, {http_error, 400, _BadRequest, Body}} ->
XML = element(1, xmerl_scan:string(binary_to_list(Body))),
Expand Down Expand Up @@ -524,3 +526,11 @@ parse_key("EventEndpointDeleted") -> event_endpoint_deleted;
parse_key("EventEndpointUpdated") -> event_endpoint_updated;
parse_key("EVentDeliveryFailure") -> event_delivery_failure;
parse_key(OtherKey) -> list_to_atom(string:to_lower(OtherKey)).

scheme_to_protocol(S) when is_list(S) -> s2p(string:to_lower(S));
scheme_to_protocol(_) -> erlang:error({sns_error, badarg}).

s2p("http://") -> "http";
s2p("https://") -> "https";
s2p(X) -> erlang:error({sns_error, {unsupported_scheme, X}}).

78 changes: 78 additions & 0 deletions test/erlcloud_sns_tests.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
-module(erlcloud_sns_tests).
-include_lib("eunit/include/eunit.hrl").
-include_lib("erlcloud/include/erlcloud_aws.hrl").

sns_publish_test_() ->
{foreach,
fun start/0,
fun stop/1,
[fun defaults_to_http/1,
fun supports_explicit_http/1,
fun supports_https/1,
fun is_case_insensitive/1,
fun doesnt_support_gopher/1,
fun doesnt_accept_non_strings/1
]}.

start() ->
meck:new(erlcloud_httpc),
meck:expect(erlcloud_httpc, request,
fun(_,_,_,_,_,_) -> mock_httpc_response() end).

stop(_) ->
meck:unload(erlcloud_httpc).

defaults_to_http(_) ->
Config = erlcloud_aws:default_config(),
erlcloud_sns:publish_to_topic("topicarn", "message", "subject", Config),
?_assertMatch({"http://sns.amazonaws.com/", _, _, _, _, Config}, request_params()).

supports_explicit_http(_) ->
Config = (erlcloud_aws:default_config())#aws_config{sns_scheme="http://"},
erlcloud_sns:publish_to_topic("topicarn", "message", "subject", Config),
?_assertMatch({"http://sns.amazonaws.com/", _, _, _, _, Config}, request_params()).

supports_https(_) ->
Config = (erlcloud_aws:default_config())#aws_config{sns_scheme="https://"},
erlcloud_sns:publish_to_topic("topicarn", "message", "subject", Config),
?_assertMatch({"https://sns.amazonaws.com/", _, _, _, _, Config}, request_params()).

is_case_insensitive(_) ->
Config = (erlcloud_aws:default_config())#aws_config{sns_scheme="HTTPS://"},
erlcloud_sns:publish_to_topic("topicarn", "message", "subject", Config),
?_assertMatch({"https://sns.amazonaws.com/", _, _, _, _, Config}, request_params()).

doesnt_support_gopher(_) ->
Config = (erlcloud_aws:default_config())#aws_config{sns_scheme="gopher://"},
?_assertError({sns_error, {unsupported_scheme,"gopher://"}},
erlcloud_sns:publish_to_topic("topicarn", "message", "subject", Config)).

doesnt_accept_non_strings(_) ->
Config = (erlcloud_aws:default_config())#aws_config{sns_scheme=https},
?_assertError({sns_error, badarg},
erlcloud_sns:publish_to_topic("topicarn", "message", "subject", Config)).


% ==================
% Internal functions
% ==================

get_values_from_history(Plist) ->
[Call1] = [ Params || {_, {erlcloud_httpc, request, Params}, _} <- Plist ],
list_to_tuple(Call1).

request_params() ->
get_values_from_history(meck:history(erlcloud_httpc)).

mock_httpc_response() ->
{ok, {{200, "ok"}, [], response_body()}}.

response_body() ->
<<"<PublishResponse xmlns='http://sns.amazonaws.com/doc/2010-03-31/'>
<PublishResult>
<MessageId>94f20ce6-13c5-43a0-9a9e-ca52d816e90b</MessageId>
</PublishResult>
<ResponseMetadata>
<RequestId>f187a3c1-376f-11df-8963-01868b7c937a</RequestId>
</ResponseMetadata>
</PublishResponse>">>.

0 comments on commit 573cce3

Please sign in to comment.