Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions lib/aws_codegen.ex
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ defmodule AWS.CodeGen do
decode: nil,
encode: nil,
endpoint_prefix: nil,
# Name of the AWS-canonical service-specific endpoint env var
# (e.g. "AWS_ENDPOINT_URL_DYNAMODB"). Derived from `service_id`
# per the AWS CLI/SDK convention: spaces -> "_", uppercased.
# See https://docs.aws.amazon.com/cli/v1/userguide/cli-configure-endpoints.html
endpoint_url_env_var: nil,
is_global: false,
hostname: nil,
json_version: nil,
Expand Down
1 change: 1 addition & 0 deletions lib/aws_codegen/post_service.ex
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ defmodule AWS.CodeGen.PostService do
signing_name: signing_name,
signature_version: AWS.CodeGen.Util.get_signature_version(service),
service_id: AWS.CodeGen.Util.get_service_id(service),
endpoint_url_env_var: AWS.CodeGen.Util.endpoint_url_env_var(service),
Comment thread
vulkoingim marked this conversation as resolved.
Outdated
target_prefix: target_prefix(spec.api)
}
end
Expand Down
1 change: 1 addition & 0 deletions lib/aws_codegen/rest_service.ex
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ defmodule AWS.CodeGen.RestService do
signing_name: signing_name,
signature_version: AWS.CodeGen.Util.get_signature_version(service),
service_id: AWS.CodeGen.Util.get_service_id(service),
endpoint_url_env_var: AWS.CodeGen.Util.endpoint_url_env_var(service),
Comment thread
vulkoingim marked this conversation as resolved.
Outdated
## TODO: metadata["targetPrefix"],
target_prefix: nil,
shapes: Shapes.collect_shapes(language, spec.api)
Expand Down
30 changes: 30 additions & 0 deletions lib/aws_codegen/util.ex
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,36 @@ defmodule AWS.CodeGen.Util do
service["traits"]["aws.api#service"]["sdkId"]
end

@doc """
Derive the AWS-canonical service-specific endpoint env var name from the
service's `sdkId` (a.k.a. `service_id`).

Per https://docs.aws.amazon.com/cli/v1/userguide/cli-configure-endpoints.html
the env var suffix is the `sdkId` with spaces replaced by `_` and the
whole string uppercased. The generic prefix is `AWS_ENDPOINT_URL_`.

Examples:

iex> AWS.CodeGen.Util.endpoint_url_env_var(%{"traits" => %{"aws.api#service" => %{"sdkId" => "DynamoDB"}}})
"AWS_ENDPOINT_URL_DYNAMODB"

iex> AWS.CodeGen.Util.endpoint_url_env_var(%{"traits" => %{"aws.api#service" => %{"sdkId" => "Elastic Beanstalk"}}})
"AWS_ENDPOINT_URL_ELASTIC_BEANSTALK"

iex> AWS.CodeGen.Util.endpoint_url_env_var(%{"traits" => %{"aws.api#service" => %{"sdkId" => "CloudTrail Data"}}})
"AWS_ENDPOINT_URL_CLOUDTRAIL_DATA"
"""
def endpoint_url_env_var(service) do
case get_service_id(service) do
nil ->
nil

service_id ->
suffix = service_id |> String.replace(" ", "_") |> String.upcase()
"AWS_ENDPOINT_URL_" <> suffix
end
end

def input_keys(action, context) do
shapes = context.shapes
input_shape = action.input["target"]
Expand Down
6 changes: 4 additions & 2 deletions priv/post.erl.eex
Comment thread
vulkoingim marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,10 @@ request(Client, Action, Input, Options) ->
<% else %>do_request(Client, Action, Input0, Options) ->
<% end %> Client1 = Client#{service => <<"<%= context.signing_name %>">><%= if context.is_global do %>,
region => <<"<%= context.credential_scope %>">><% end %>},
Host = build_host(<<"<%= context.endpoint_prefix %>">>, Client1),
URL = build_url(Host, Client1),
DefaultHost = build_host(<<"<%= context.endpoint_prefix %>">>, Client1),
{URL, Host} = aws_util:apply_endpoint_url_override(
build_url(DefaultHost, Client1), DefaultHost, <<"/">>,
<<"<%= context.endpoint_url_env_var %>">>),
Headers = [
{<<"Host">>, Host},
{<<"Content-Type">>, <<"<%= context.content_type %>">>}<%= if context.protocol == "json" do %>,
Expand Down
11 changes: 7 additions & 4 deletions priv/rest.erl.eex
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,13 @@ do_request(Client, Method, Path, Query, Headers0, Input, Options, SuccessStatusC
Client1 = Client#{service => <<"<%= context.signing_name %>">><%= if context.is_global do %>,
region => <<"<%= context.credential_scope %>">><% end %>},
<%= if context.endpoint_prefix == "s3-control" do %>AccountId = proplists:get_value(<<"x-amz-account-id">>, Headers0),
Host = build_host(AccountId, <<"<%= context.endpoint_prefix %>">>, Client1),<% else %><%= if AWS.CodeGen.RestService.Context.s3_context?(context) do %>Host = build_host(<<"<%= context.endpoint_prefix %>">>, Client1, Bucket),<%else %>Host = build_host(<<"<%= context.endpoint_prefix %>">>, Client1),<% end %><% end %>
URL0 = build_url(Host, Path, Client1<%= if AWS.CodeGen.RestService.Context.s3_context?(context) do %>, Bucket<% end %>),
URL = aws_request:add_query(URL0, Query),
DefaultHost = build_host(AccountId, <<"<%= context.endpoint_prefix %>">>, Client1),<% else %><%= if AWS.CodeGen.RestService.Context.s3_context?(context) do %>DefaultHost = build_host(<<"<%= context.endpoint_prefix %>">>, Client1, Bucket),<%else %>DefaultHost = build_host(<<"<%= context.endpoint_prefix %>">>, Client1),<% end %><% end %>
URL0 = build_url(DefaultHost, Path, Client1<%= if AWS.CodeGen.RestService.Context.s3_context?(context) do %>, Bucket<% end %>),
PathBin = erlang:iolist_to_binary(Path),
{URL1, Host} = aws_util:apply_endpoint_url_override(
URL0, DefaultHost, PathBin,
<<"<%= context.endpoint_url_env_var %>">>),
URL = aws_request:add_query(URL1, Query),
AdditionalHeaders1 = [ {<<"Host">>, Host}
, {<<"Content-Type">>, <<"<%= context.content_type %>">>}
],
Expand Down Expand Up @@ -332,7 +336,6 @@ build_host(EndpointPrefix, #{endpoint := Endpoint}) ->
aws_util:binary_join([EndpointPrefix, Endpoint], <<".">>).<% else %>
build_host(EndpointPrefix, #{region := Region, endpoint := Endpoint}) ->
aws_util:binary_join([EndpointPrefix, Region, Endpoint], <<".">>).<% end %><% end %><% end %><% end %>

<%= if AWS.CodeGen.RestService.Context.s3_context?(context) do %>build_url(Host0, Path0, Client, Bucket) ->
Proto = aws_client:proto(Client),
%% Mocks are notoriously bad with host-style requests, just skip it and use path-style for anything local
Expand Down
1 change: 1 addition & 0 deletions test/aws_codegen/rest_service_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ defmodule AWS.CodeGen.RestServiceTest do
module_name: "AWS.CloudTrailData",
protocol: "rest-json",
service_id: "CloudTrail Data",
endpoint_url_env_var: "AWS_ENDPOINT_URL_CLOUDTRAIL_DATA",
signature_version: "v4",
signing_name: "cloudtrail-data",
target_prefix: nil
Expand Down
32 changes: 32 additions & 0 deletions test/aws_codegen/util_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
defmodule AWS.CodeGen.UtilTest do
use ExUnit.Case, async: true
doctest AWS.CodeGen.Util

alias AWS.CodeGen.Util

describe "endpoint_url_env_var/1" do
test "derives the env var from a single-word sdkId" do
service = build_service("DynamoDB")
assert Util.endpoint_url_env_var(service) == "AWS_ENDPOINT_URL_DYNAMODB"
end

test "replaces interior spaces with underscores and uppercases the result" do
service = build_service("Elastic Beanstalk")
assert Util.endpoint_url_env_var(service) == "AWS_ENDPOINT_URL_ELASTIC_BEANSTALK"
end

test "handles multi-word sdkIds" do
service = build_service("CloudTrail Data")
assert Util.endpoint_url_env_var(service) == "AWS_ENDPOINT_URL_CLOUDTRAIL_DATA"
end

test "returns nil when the sdkId is missing" do
assert Util.endpoint_url_env_var(%{"traits" => %{}}) == nil
assert Util.endpoint_url_env_var(%{}) == nil
end
end

defp build_service(sdk_id) do
%{"traits" => %{"aws.api#service" => %{"sdkId" => sdk_id}}}
end
end
Loading