diff --git a/lib/hanami/lambda/env.rb b/lib/hanami/lambda/env.rb new file mode 100644 index 0000000..314b231 --- /dev/null +++ b/lib/hanami/lambda/env.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +require "rack" + +module Hanami + module Lambda + class Env + def initialize(event:, headers:, context:) + @event = event + @headers = headers + @content_type = extract_content_type + @http_headers = transform_http_headers + @context = context + end + + def to_h + { + ::Rack::REQUEST_METHOD => @event["httpMethod"], + ::Rack::PATH_INFO => @event["path"] || "", + ::Rack::RACK_VERSION => ::Rack.release, + ::Rack::RACK_INPUT => StringIO.new(@event["body"] || ""), + ::Hanami::Lambda::LAMBDA_EVENT => @event, + ::Hanami::Lambda::LAMBDA_CONTEXT => @context + }.tap do |env| + env["CONTENT_TYPE"] = @content_type if @content_type + end.merge(@http_headers) + end + + private + + def extract_content_type + @headers.delete("Content-Type") || + @headers.delete("content-type") || + @headers.delete("CONTENT_TYPE") + end + + def transform_http_headers + @headers.transform_keys { |k| "HTTP_#{k.upcase.tr('-', '_')}" } + end + end + end +end diff --git a/lib/hanami/lambda/rack.rb b/lib/hanami/lambda/rack.rb index 9fe9ec7..7fc8f3b 100644 --- a/lib/hanami/lambda/rack.rb +++ b/lib/hanami/lambda/rack.rb @@ -41,19 +41,7 @@ def call(event:, context:) # # @since 0.1.0 def build_env(event, headers, context) - { - ::Rack::REQUEST_METHOD => event["httpMethod"], - ::Rack::PATH_INFO => event["path"] || "", - ::Rack::RACK_VERSION => ::Rack.release, - ::Rack::RACK_INPUT => StringIO.new(event["body"] || ""), - ::Hanami::Lambda::LAMBDA_EVENT => event, - ::Hanami::Lambda::LAMBDA_CONTEXT => context - }.tap do |env| - content_type = headers.delete("Content-Type") || - headers.delete("content-type") || - headers.delete("CONTENT_TYPE") - env["CONTENT_TYPE"] = content_type if content_type - end.merge(headers.transform_keys { |k| "HTTP_#{k.upcase.tr('-', '_')}" }) + Env.new(event: event, headers: headers, context: context).to_h end end end diff --git a/sig/hanami/lambda/env.rbs b/sig/hanami/lambda/env.rbs new file mode 100644 index 0000000..a78abb1 --- /dev/null +++ b/sig/hanami/lambda/env.rbs @@ -0,0 +1,29 @@ +module Hanami + module Lambda + class Env + @event: Hash[::String, String? | Hash] + + @headers: Hash[::String, ::String] + + @content_type: ::String + + @http_headers: Hash[::String, ::String] + + @context: Object + + def initialize: (event: Hash[::String, String? | Hash], headers: Hash[::String, ::String], context: Object) -> void + + # Build a hash of the Rack environment + # + # @return [Hash] the hash of Rack environment + # + def to_h: () -> ::Hash[::String?, (::String? | Hash[::String, String? | Hash] | Object)] + + private + + def extract_content_type: () -> ::String? + + def transform_http_headers: () -> Hash[::String, ::String] + end + end +end diff --git a/sig/shims/rack.rbs b/sig/shims/rack.rbs new file mode 100644 index 0000000..d9b6b3d --- /dev/null +++ b/sig/shims/rack.rbs @@ -0,0 +1,5 @@ +module Rack + class Headers + KNOWN_HEADERS: Hash[String, String] + end +end diff --git a/spec/hanami/lambda/env_spec.rb b/spec/hanami/lambda/env_spec.rb new file mode 100644 index 0000000..2348889 --- /dev/null +++ b/spec/hanami/lambda/env_spec.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +RSpec.describe Hanami::Lambda::Env do + subject(:env) { described_class.new(event: event, headers: headers, context: context) } + + let(:event) do + { + "httpMethod" => "GET", + "path" => "/", + "body" => "" + } + end + + let(:headers) do + { + "Content-Type" => "text/plain", + "X-Custom-Header" => "Custom Value" + } + end + + let(:context) { double(:context) } + + describe "#to_h" do + subject(:hash) { env.to_h } + + it { is_expected.to include(::Hanami::Lambda::LAMBDA_EVENT) } + it { is_expected.to include(::Hanami::Lambda::LAMBDA_CONTEXT) } + it { is_expected.to include("CONTENT_TYPE" => "text/plain") } + it { is_expected.to include("HTTP_X_CUSTOM_HEADER" => "Custom Value") } + end +end diff --git a/spec/hanami/lambda/rack_spec.rb b/spec/hanami/lambda/rack_spec.rb index dec496a..05bffaf 100644 --- a/spec/hanami/lambda/rack_spec.rb +++ b/spec/hanami/lambda/rack_spec.rb @@ -33,13 +33,4 @@ it { is_expected.to include(body: "Hello from Rack") } it { is_expected.to include(headers: {}) } end - - describe "#env" do - subject(:env) { rack.build_env(event, headers, context) } - - it { is_expected.to include(::Hanami::Lambda::LAMBDA_EVENT) } - it { is_expected.to include(::Hanami::Lambda::LAMBDA_CONTEXT) } - it { is_expected.to include("CONTENT_TYPE" => "text/plain") } - it { is_expected.to include("HTTP_X_CUSTOM_HEADER" => "Custom Value") } - end end