Skip to content

Commit 1625361

Browse files
committed
Fully remove httpc
1 parent 4521569 commit 1625361

File tree

3 files changed

+193
-50
lines changed

3 files changed

+193
-50
lines changed

deps/rabbitmq_aws/src/rabbitmq_aws.erl

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
parse_uri/1,
1919
set_region/1,
2020
ensure_imdsv2_token_valid/0,
21-
api_get_request/2]).
21+
api_get_request/2,
22+
status_text/1]).
2223

2324
%% gen-server exports
2425
-export([start_link/0,
@@ -623,15 +624,15 @@ get_or_create_gun_connection(State, Host, Port, Path, Options) ->
623624
HostKey = get_connection_key(Host, Port, Path, Options),
624625
case maps:get(HostKey, State#state.gun_connections, undefined) of
625626
undefined ->
626-
create_gun_connection(State, Host, Port, Path, HostKey, Options);
627+
create_gun_connection(State, Host, Port, HostKey, Options);
627628
ConnPid ->
628629
case is_process_alive(ConnPid) andalso gun:info(ConnPid) =/= undefined of
629630
true ->
630631
{ConnPid, State};
631632
false ->
632633
% Connection is dead, create new one
633634
gun:close(ConnPid),
634-
create_gun_connection(State, Host, Port, Path, HostKey, Options)
635+
create_gun_connection(State, Host, Port, HostKey, Options)
635636
end
636637
end.
637638

@@ -641,7 +642,7 @@ get_connection_key(Host, Port, Path, Options) ->
641642
false -> Host ++ ":" ++ integer_to_list(Port) % Per-host (default)
642643
end.
643644

644-
create_gun_connection(State, Host, Port, Path, HostKey, Options) ->
645+
create_gun_connection(State, Host, Port, HostKey, Options) ->
645646
% Map HTTP version to Gun protocols, always include http as fallback
646647
HttpVersion = proplists:get_value(version, Options, "HTTP/1.1"),
647648
Protocols = case HttpVersion of
@@ -674,21 +675,26 @@ create_gun_connection(State, Host, Port, Path, HostKey, Options) ->
674675

675676
parse_uri(URI) ->
676677
case string:split(URI, "://", leading) of
677-
[_Scheme, Rest] ->
678+
[Scheme, Rest] ->
678679
case string:split(Rest, "/", leading) of
679680
[HostPort] ->
680-
{Host, Port} = parse_host_port(HostPort),
681+
{Host, Port} = parse_host_port(HostPort, Scheme),
681682
{Host, Port, "/"};
682683
[HostPort, Path] ->
683-
{Host, Port} = parse_host_port(HostPort),
684+
{Host, Port} = parse_host_port(HostPort, Scheme),
684685
{Host, Port, "/" ++ Path}
685686
end
686687
end.
687688

688-
parse_host_port(HostPort) ->
689+
parse_host_port(HostPort, Scheme) ->
690+
DefaultPort = case Scheme of
691+
"https" -> 443;
692+
"http" -> 80;
693+
_ -> 443 % Fallback to HTTPS
694+
end,
689695
case string:split(HostPort, ":", trailing) of
690696
[Host] ->
691-
{Host, 443}; % Default HTTPS port
697+
{Host, DefaultPort};
692698
[Host, PortStr] ->
693699
{Host, list_to_integer(PortStr)}
694700
end.

deps/rabbitmq_aws/src/rabbitmq_aws_config.erl

Lines changed: 88 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -615,8 +615,10 @@ maybe_get_role_from_instance_metadata() ->
615615
%% Instance Metadata service, returning the Region if successful.
616616
%% end.
617617
parse_az_response({error, _}) -> {error, undefined};
618-
parse_az_response({ok, {{_, 200, _}, _, Body}})
619-
-> {ok, region_from_availability_zone(Body)};
618+
parse_az_response({ok, {{_, 200, _}, _, Body}}) when is_binary(Body) ->
619+
{ok, region_from_availability_zone(binary_to_list(Body))};
620+
parse_az_response({ok, {{_, 200, _}, _, Body}}) ->
621+
{ok, region_from_availability_zone(Body)};
620622
parse_az_response({ok, {{_, _, _}, _, _}}) -> {error, undefined}.
621623

622624

@@ -626,7 +628,8 @@ parse_az_response({ok, {{_, _, _}, _, _}}) -> {error, undefined}.
626628
%% body value is the string to process.
627629
%% end.
628630
parse_body_response({error, _}) -> {error, undefined};
629-
parse_body_response({ok, {{_, 200, _}, _, Body}}) -> {ok, Body};
631+
parse_body_response({ok, {{_, 200, _}, _, Body}}) when is_binary(Body) -> {ok, binary_to_list(Body)};
632+
parse_body_response({ok, {{_, 200, _}, _, Body}}) when is_list(Body) -> {ok, Body};
630633
parse_body_response({ok, {{_, 401, _}, _, _}}) ->
631634
?LOG_ERROR(get_instruction_on_instance_metadata_error("Unauthorized instance metadata service request.")),
632635
{error, undefined};
@@ -655,9 +658,35 @@ parse_credentials_response({ok, {{_, 200, _}, _, Body}}) ->
655658
%% @doc Wrap httpc:get/4 to simplify Instance Metadata service v2 requests
656659
%% @end
657660
perform_http_get_instance_metadata(URL) ->
658-
?LOG_DEBUG("Querying instance metadata service: ~tp", [URL]),
659-
httpc:request(get, {URL, instance_metadata_request_headers()},
660-
[{timeout, ?DEFAULT_HTTP_TIMEOUT}], []).
661+
?LOG_DEBUG("Querying instance metadata service: ~tp", [URL]),
662+
% Parse metadata service URL
663+
{Host, Port, Path} = rabbitmq_aws:parse_uri(URL),
664+
% Simple Gun connection for metadata service
665+
Opts = #{transport => tcp, protocols => [http]}, % HTTP only, no TLS
666+
case gun:open(Host, Port, Opts) of
667+
{ok, ConnPid} ->
668+
case gun:await_up(ConnPid, 5000) of
669+
{ok, _Protocol} ->
670+
Headers = instance_metadata_request_headers(),
671+
StreamRef = gun:get(ConnPid, Path, Headers),
672+
Result = case gun:await(ConnPid, StreamRef, ?DEFAULT_HTTP_TIMEOUT) of
673+
{response, fin, Status, RespHeaders} ->
674+
{ok, {{http_version, Status, rabbitmq_aws:status_text(Status)}, RespHeaders, <<>>}};
675+
{response, nofin, Status, RespHeaders} ->
676+
{ok, Body} = gun:await_body(ConnPid, StreamRef, ?DEFAULT_HTTP_TIMEOUT),
677+
{ok, {{http_version, Status, rabbitmq_aws:status_text(Status)}, RespHeaders, Body}};
678+
{error, Reason} ->
679+
{error, Reason}
680+
end,
681+
gun:close(ConnPid),
682+
Result;
683+
{error, Reason} ->
684+
gun:close(ConnPid),
685+
{error, Reason}
686+
end;
687+
{error, Reason} ->
688+
{error, Reason}
689+
end.
661690

662691
-spec get_instruction_on_instance_metadata_error(string()) -> string().
663692
%% @doc Return error message on failures related to EC2 Instance Metadata Service with a reference to AWS document.
@@ -717,6 +746,7 @@ region_from_availability_zone(Value) ->
717746
%% @doc Attempt to obtain EC2 IMDSv2 token.
718747
%% @end
719748
load_imdsv2_token() ->
749+
<<<<<<< HEAD
720750
TokenUrl = imdsv2_token_url(),
721751
?LOG_INFO("Attempting to obtain EC2 IMDSv2 token from ~tp ...", [TokenUrl]),
722752
case httpc:request(put, {TokenUrl, [{?METADATA_TOKEN_TTL_HEADER, integer_to_list(?METADATA_TOKEN_TTL_SECONDS)}]},
@@ -733,6 +763,58 @@ load_imdsv2_token() ->
733763
"Falling back to EC2 IMDSv1 for now. It is recommended to use EC2 IMDSv2."), [Other]),
734764
undefined
735765
end.
766+
=======
767+
TokenUrl = imdsv2_token_url(),
768+
rabbit_log:info("Attempting to obtain EC2 IMDSv2 token from ~tp ...", [TokenUrl]),
769+
% Parse metadata service URL
770+
{Host, Port, Path} = rabbitmq_aws:parse_uri(TokenUrl),
771+
% Simple Gun connection for metadata service
772+
Opts = #{transport => tcp, protocols => [http]}, % HTTP only, no TLS
773+
case gun:open(Host, Port, Opts) of
774+
{ok, ConnPid} ->
775+
case gun:await_up(ConnPid, 5000) of
776+
{ok, _Protocol} ->
777+
% PUT request with IMDSv2 token TTL header
778+
Headers = [{?METADATA_TOKEN_TTL_HEADER, integer_to_list(?METADATA_TOKEN_TTL_SECONDS)}],
779+
StreamRef = gun:put(ConnPid, Path, Headers, <<>>),
780+
Result = case gun:await(ConnPid, StreamRef, ?DEFAULT_HTTP_TIMEOUT) of
781+
{response, fin, 200, _RespHeaders} ->
782+
rabbit_log:debug("Successfully obtained EC2 IMDSv2 token."),
783+
<<>>; % Empty body for fin response
784+
{response, nofin, 200, _RespHeaders} ->
785+
{ok, Body} = gun:await_body(ConnPid, StreamRef, ?DEFAULT_HTTP_TIMEOUT),
786+
rabbit_log:debug("Successfully obtained EC2 IMDSv2 token."),
787+
binary_to_list(Body);
788+
{response, _, 400, _RespHeaders} ->
789+
rabbit_log:warning("Failed to obtain EC2 IMDSv2 token: Missing or Invalid Parameters – The PUT request is not valid."),
790+
undefined;
791+
{error, Reason} ->
792+
rabbit_log:warning(
793+
get_instruction_on_instance_metadata_error("Failed to obtain EC2 IMDSv2 token: ~tp. "
794+
"Falling back to EC2 IMDSv1 for now. It is recommended to use EC2 IMDSv2."), [Reason]),
795+
undefined;
796+
Other ->
797+
rabbit_log:warning(
798+
get_instruction_on_instance_metadata_error("Failed to obtain EC2 IMDSv2 token: ~tp. "
799+
"Falling back to EC2 IMDSv1 for now. It is recommended to use EC2 IMDSv2."), [Other]),
800+
undefined
801+
end,
802+
gun:close(ConnPid),
803+
Result;
804+
{error, Reason} ->
805+
gun:close(ConnPid),
806+
rabbit_log:warning(
807+
get_instruction_on_instance_metadata_error("Failed to connect for EC2 IMDSv2 token: ~tp. "
808+
"Falling back to EC2 IMDSv1 for now. It is recommended to use EC2 IMDSv2."), [Reason]),
809+
undefined
810+
end;
811+
{error, Reason} ->
812+
rabbit_log:warning(
813+
get_instruction_on_instance_metadata_error("Failed to open connection for EC2 IMDSv2 token: ~tp. "
814+
"Falling back to EC2 IMDSv1 for now. It is recommended to use EC2 IMDSv2."), [Reason]),
815+
undefined
816+
end.
817+
>>>>>>> f04e9ce16a (Fully remove httpc)
736818

737819

738820
-spec instance_metadata_request_headers() -> headers().

0 commit comments

Comments
 (0)