Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
15 changes: 12 additions & 3 deletions lib/aws_codegen/rest_service.ex
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
defmodule AWS.CodeGen.RestService do
alias AWS.CodeGen.Docstring
alias AWS.CodeGen.Service
alias AWS.CodeGen.Shapes

defmodule Action do
alias AWS.CodeGen.RestService.Parameter
Expand All @@ -16,6 +17,7 @@ defmodule AWS.CodeGen.RestService do
query_parameters: [],
request_header_parameters: [],
response_header_parameters: [],
send_body_as_binary?: false,
language: nil

def method(action) do
Expand Down Expand Up @@ -172,11 +174,15 @@ defmodule AWS.CodeGen.RestService do
end

defp collect_actions(language, api_spec, doc_spec) do
shapes = api_spec["shapes"]

Enum.map(api_spec["operations"], fn {operation, _metadata} ->
operation_spec = api_spec["operations"][operation]

url_parameters = collect_url_parameters(language, api_spec, operation)
query_parameters = collect_query_parameters(language, api_spec, operation)
request_header_parameters = collect_request_header_parameters(language, api_spec, operation)
method = api_spec["operations"][operation]["http"]["method"]
method = operation_spec["http"]["method"]

len_for_method =
case method do
Expand All @@ -187,6 +193,8 @@ defmodule AWS.CodeGen.RestService do
3
end

input_shape = Shapes.get_input_shape(operation_spec)

%Action{
arity: length(url_parameters) + len_for_method,
docstring:
Expand All @@ -195,15 +203,16 @@ defmodule AWS.CodeGen.RestService do
doc_spec["operations"][operation]
),
method: method,
request_uri: api_spec["operations"][operation]["http"]["requestUri"],
success_status_code: api_spec["operations"][operation]["http"]["responseCode"],
request_uri: operation_spec["http"]["requestUri"],
success_status_code: operation_spec["http"]["responseCode"],
function_name: AWS.CodeGen.Name.to_snake_case(operation),
name: operation,
url_parameters: url_parameters,
query_parameters: query_parameters,
request_header_parameters: request_header_parameters,
response_header_parameters:
collect_response_header_parameters(language, api_spec, operation),
send_body_as_binary?: Shapes.send_body_as_binary?(shapes, input_shape),
language: language
}
end)
Expand Down
19 changes: 19 additions & 0 deletions lib/aws_codegen/shapes.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
defmodule AWS.CodeGen.Shapes do
@moduledoc false

def get_input_shape(operation_spec) do
get_in(operation_spec, ["input", "shape"])
end

def send_body_as_binary?(shapes, input_shape) do
with %{"shape" => inner_shape} = inner_spec <-
get_in(shapes, [input_shape, "members", "Body"]),
true <- !Map.has_key?(inner_spec, "location"),
%{"type" => type} <- Map.get(shapes, inner_shape) do
type in ~w(blob string)
else
_ ->
false
end
end
end
14 changes: 11 additions & 3 deletions priv/rest.erl.eex
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
Query_ = [],
Input = Input1,
<% end %><%= if length(action.response_header_parameters) > 0 do %>
case request(Client, Method, Path, Query_, Headers, Input, Options, SuccessStatusCode) of
case request(Client, Method, Path, Query_, Headers, Input, Options<%= if action.send_body_as_binary? do %> ++ [{should_send_body_as_binary, true}]<% end %>, SuccessStatusCode) of
{ok, Body0, {_, ResponseHeaders, _} = Response} ->
ResponseHeadersParams =
[<%= for parameter <- Enum.drop action.response_header_parameters, -1 do %>
Expand All @@ -101,7 +101,7 @@
Result ->
Result
end.<% else %>
request(Client, Method, Path, Query_, Headers, Input, Options, SuccessStatusCode).<% end %>
request(Client, Method, Path, Query_, Headers, Input, Options<%= if action.send_body_as_binary? do %> ++ [{should_send_body_as_binary, true}]<% end %>, SuccessStatusCode).<% end %>
<% end %><% end %>
%%====================================================================
%% Internal functions
Expand All @@ -125,7 +125,15 @@ request(Client, Method, Path, Query, Headers0, Input, Options, SuccessStatusCode
, {<<"Content-Type">>, <<"<%= context.content_type %>">>}
],
Headers1 = aws_request:add_headers(AdditionalHeaders, Headers0),
Payload = encode_payload(Input),

Payload =
case proplists:get_value(should_send_body_as_binary, Options) of
true ->
maps:get(<<"Body">>, Input, <<"">>);
undefined ->
encode_payload(Input)
end,

MethodBin = aws_request:method_to_binary(Method),
SignedHeaders = aws_request:sign_request(Client1, MethodBin, URL, Headers1, Payload),
Response = hackney:request(Method, URL, SignedHeaders, Payload, Options),
Expand Down
10 changes: 10 additions & 0 deletions priv/rest.ex.eex
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ defmodule <%= context.module_name %> do
:response_header_parameters,
<%= inspect((for param <- action.response_header_parameters, do: {param.location_name, param.name}), pretty: true) %>
)<% end %>

Request.request_rest(client, metadata(), :get, url_path, query_params, headers, nil, options, <%= inspect(action.success_status_code) %>)<% else %>
def <%= action.function_name %>(%Client{} = client<%= AWS.CodeGen.RestService.function_parameters(action) %>, input, options \\ []) do
url_path = "<%= AWS.CodeGen.RestService.Action.url_path(action) %>"<%= if length(action.request_header_parameters) > 0 do %>
Expand All @@ -70,6 +71,15 @@ defmodule <%= context.module_name %> do
:response_header_parameters,
<%= inspect((for param <- action.response_header_parameters, do: {param.location_name, param.name}), pretty: true) %>
)<% end %>

<%= if action.send_body_as_binary? do %>
options = Keyword.put(
options,
:send_body_as_binary?,
true
)
<% end %>

Request.request_rest(client, metadata(), <%= AWS.CodeGen.RestService.Action.method(action) %>, url_path, query_params, headers, input, options, <%= inspect(action.success_status_code) %>)<% end %>
end<% end %>
end
34 changes: 34 additions & 0 deletions test/aws_codegen/shapes_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
defmodule AWS.CodeGen.ShapesTest do
use ExUnit.Case
alias AWS.CodeGen.Shapes

test "send_body_as_binary?/2" do
shapes = %{
"Body" => %{"type" => "blob"},
"PutObjectRequest" => %{
"type" => "structure",
"members" => %{
"Body" => %{
"shape" => "Body",
"streaming" => true
}
}
},
"PutObjectAclRequest" => %{
"type" => "structure",
"members" => %{
"ACL" => %{
"shape" => "ObjectCannedACL",
"location" => "header",
"locationName" => "x-amz-acl"
}
}
}
}

assert Shapes.send_body_as_binary?(shapes, "PutObjectRequest")

refute Shapes.send_body_as_binary?(shapes, "PutObjectAclRequest")
refute Shapes.send_body_as_binary?(shapes, "AnotherShape")
end
end