Class: Jets::Server::LambdaAwsProxy
- Inherits:
-
Object
- Object
- Jets::Server::LambdaAwsProxy
- Defined in:
- lib/jets/server/lambda_aws_proxy.rb
Overview
This doesnt really need to be middleware
Constant Summary collapse
- CASING_MAP =
Annoying. The headers part of the AWS Lambda proxy structure does not consisently use the same casing scheme for the header keys. Sometimes it looks like this:
Accept-Encoding
and sometimes it looks like this:
cache-control
Map for special cases when the casing doesn’t match.
{ "Cache-Control" => "cache-control", "Content-Type" => "content-type", "Origin" => "origin", "Upgrade-Insecure-Requests" => "upgrade-insecure-requests", }
Instance Method Summary collapse
- #build_event ⇒ Object
- #find_controller_action ⇒ Object
- #find_controller_class ⇒ Object
-
#get_body ⇒ Object
To get the post body: rack.input: #<StringIO:0x007f8ccf8db9a0>.
-
#initialize(route, env) ⇒ LambdaAwsProxy
constructor
A new instance of LambdaAwsProxy.
- #query_string_parameters ⇒ Object
-
#request_headers ⇒ Object
Map rack env headers to Api Gateway event headers.
- #response ⇒ Object
Constructor Details
#initialize(route, env) ⇒ LambdaAwsProxy
Returns a new instance of LambdaAwsProxy.
7 8 9 10 11 12 13 14 |
# File 'lib/jets/server/lambda_aws_proxy.rb', line 7 def initialize(route, env) @route = route @env = env puts "Rack env:".colorize(:yellow) @env.each do |k,v| puts "#{k}: #{v}" end end |
Instance Method Details
#build_event ⇒ Object
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/jets/server/lambda_aws_proxy.rb', line 35 def build_event resource = @route.path(:api_gateway) # posts/{id}/edit path = @env['PATH_INFO'].sub('/','') # remove beginning slash { "resource" => "/#{resource}", # "/posts/{id}/edit" "path" => @env['PATH_INFO'], # /posts/tung/edit "httpMethod" => @env['REQUEST_METHOD'], # GET "headers" => request_headers, "queryStringParameters" => query_string_parameters, "pathParameters" => @route.extract_parameters(path), "stageVariables" => nil, "requestContext" => {}, "body" => get_body, "isBase64Encoded" => false, } end |
#find_controller_action ⇒ Object
130 131 132 |
# File 'lib/jets/server/lambda_aws_proxy.rb', line 130 def find_controller_action @route.action_name end |
#find_controller_class ⇒ Object
125 126 127 128 |
# File 'lib/jets/server/lambda_aws_proxy.rb', line 125 def find_controller_class # posts#edit => PostsController @route.controller_name.constantize end |
#get_body ⇒ Object
To get the post body:
rack.input: #<StringIO:0x007f8ccf8db9a0>
115 116 117 118 119 120 121 122 123 |
# File 'lib/jets/server/lambda_aws_proxy.rb', line 115 def get_body # @env["rack.input"] is always provided by rack and we should make # the test data always have rack.input to mimic rack, but but handling # it this way because it's simpler. input = @env["rack.input"] || StringIO.new body = input.read # return nil for blank string, because thats what Lambda AWS_PROXY does body unless body.empty? end |
#query_string_parameters ⇒ Object
109 110 111 |
# File 'lib/jets/server/lambda_aws_proxy.rb', line 109 def query_string_parameters Rack::Utils.parse_nested_query(@env['QUERY_STRING']) end |
#request_headers ⇒ Object
Map rack env headers to Api Gateway event headers. Most rack env headers are prepended by HTTP_.
Some API Gateway Lambda Proxy are also in the rack env headers. Example:
"X-Amz-Cf-Id": "W8DF6J-lx1bkV00eCiBwIq5dldTSGGiG4BinJlxvN_4o8fCZtbsVjw==",
"X-Amzn-Trace-Id": "Root=1-5a0dc1ac-58a7db712a57d6aa4186c2ac",
"X-Forwarded-For": "88.88.88.88, 54.239.203.117",
"X-Forwarded-Port": "443",
"X-Forwarded-Proto": "https",
For sample dump of the event headers, check out:
spec/fixtures/samples/event-headers-form-post.json
We generally do add those API Gateway Lambda specific headers because they would be fake anyway and by not adding them we can distinguish a local request from a remote request on API Gateway.
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/jets/server/lambda_aws_proxy.rb', line 83 def request_headers headers = @env.select { |k,v| k =~ /^HTTP_/ }.inject({}) do |h,(k,v)| # map things like HTTP_USER_AGENT to "User-Agent" key = k.sub('HTTP_','').split('_').map(&:capitalize).join('-') h[key] = v h end # Content type is not prepended with HTTP_ but is part of Lambda's event headers thankfully headers["Content-Type"] = @env["CONTENT_TYPE"] if @env["CONTENT_TYPE"] # Adjust the casing so it matches the Lambda AWS Proxy's structure CASING_MAP.each do |nice_casing, bad_casing| if headers.key?(nice_casing) headers[bad_casing] = headers.delete(nice_casing) end end # Way to fake X-Amzn-Trace-Id which on_aws? helper checks. # This is how we distinguish a request from API gateway vs local. if ENV['JETS_ON_AWS'] headers["X-Amzn-Trace-Id"] = "Root=fake-trace-id" end headers end |
#response ⇒ Object
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/jets/server/lambda_aws_proxy.rb', line 16 def response event = build_event context = {} controller_class = find_controller_class controller_action = find_controller_action fun = Jets::PolyFun.new(controller_class, controller_action) resp = fun.run(event, context) # check the logs for polymorphic function errors # Map lambda proxy response format to rack format status = resp["statusCode"] headers = resp["headers"] || {} headers = {'Content-Type' => 'text/html'}.merge(headers) body = resp["body"] [status, headers, [body]] end |