2020# Global object that responds to the call method. Stay outside of the handler
2121# to take advantage of container reuse
2222$app ||= Rack ::Builder . parse_file ( "#{ __dir__ } /app/config.ru" ) . first
23+ ENV [ 'RACK_ENV' ] ||= 'production'
2324
24- def handler ( event :, context :)
25+
26+ def lambda_handler ( event :, context :)
2527 # Check if the body is base64 encoded. If it is, try to decode it
26- body =
27- if event [ 'isBase64Encoded ' ]
28- Base64 . decode64 ( event [ 'body' ] )
29- else
30- event [ 'body' ]
31- end
28+ body = if event [ 'isBase64Encoded' ]
29+ Base64 . decode64 event [ 'body ' ]
30+ else
31+ event [ 'body' ]
32+ end || ''
33+
3234 # Rack expects the querystring in plain text, not a hash
33- querystring = Rack ::Utils . build_query ( event [ 'queryStringParameters' ] ) if event [ 'queryStringParameters' ]
35+ headers = event . fetch 'headers' , { }
36+
3437 # Environment required by Rack (http://www.rubydoc.info/github/rack/rack/file/SPEC)
3538 env = {
36- 'REQUEST_METHOD' => event [ 'httpMethod' ] ,
39+ 'REQUEST_METHOD' => event . fetch ( 'httpMethod' ) ,
3740 'SCRIPT_NAME' => '' ,
38- 'PATH_INFO' => event [ 'path' ] || '' ,
39- 'QUERY_STRING' => querystring || '' ,
40- 'SERVER_NAME' => 'localhost' ,
41- 'SERVER_PORT' => 443 ,
42- 'CONTENT_TYPE' => event [ 'headers' ] [ 'content-type' ] ,
41+ 'PATH_INFO' => event . fetch ( 'path' , '' ) ,
42+ 'QUERY_STRING' => Rack ::Utils . build_query ( event [ 'queryStringParameters' ] || { } ) ,
43+ 'SERVER_NAME' => headers . fetch ( 'Host' , 'localhost' ) ,
44+ 'SERVER_PORT' => headers . fetch ( 'X-Forwarded-Port' , 443 ) . to_s ,
4345
4446 'rack.version' => Rack ::VERSION ,
45- 'rack.url_scheme' => ' https',
46- 'rack.input' => StringIO . new ( body || '' ) ,
47+ 'rack.url_scheme' => headers . fetch ( 'CloudFront-Forwarded-Proto' ) { headers . fetch ( 'X-Forwarded-Proto' , ' https') } ,
48+ 'rack.input' => StringIO . new ( body ) ,
4749 'rack.errors' => $stderr,
4850 }
51+
4952 # Pass request headers to Rack if they are available
50- unless event [ 'headers' ] . nil?
51- event [ 'headers' ] . each { |key , value | env [ "HTTP_#{ key } " ] = value }
53+ headers . each_pair do |key , value |
54+ # 'CloudFront-Forwarded-Proto' => 'CLOUDFRONT_FORWARDED_PROTO'
55+ # Content-Type and Content-Length are handled specially per the Rack SPEC linked above.
56+ name = key . upcase . gsub '-' , '_'
57+ header = case name
58+ when 'CONTENT_TYPE' , 'CONTENT_LENGTH'
59+ name
60+ else
61+ "HTTP_#{ name } "
62+ end
63+ env [ header ] = value . to_s
5264 end
5365
5466 begin
5567 # Response from Rack must have status, headers and body
56- status , headers , body = $app. call ( env )
68+ status , headers , body = $app. call env
5769
5870 # body is an array. We combine all the items to a single string
5971 body_content = ""
@@ -68,17 +80,18 @@ def handler(event:, context:)
6880 'headers' => headers ,
6981 'body' => body_content
7082 }
71- if event [ 'requestContext' ] . key ?( 'elb' )
83+ if event [ 'requestContext' ] . has_key ?( 'elb' )
7284 # Required if we use Application Load Balancer instead of API Gateway
7385 response [ 'isBase64Encoded' ] = false
7486 end
75- rescue Exception => msg
76- # If there is any exception, we return a 500 error with an error message
87+ rescue Exception => exception
88+ # If there is _any_ exception, we return a 500 error with an error message
7789 response = {
7890 'statusCode' => 500 ,
79- 'body' => msg
91+ 'body' => exception . message
8092 }
8193 end
94+
8295 # By default, the response serializer will call #to_json for us
8396 response
8497end
0 commit comments