in kong/kong/plugins/aws-lambda/handler.lua [171:375]
function AWSLambdaHandler:access(conf)
local upstream_body = kong.table.new(0, 6)
local ctx = ngx.ctx
if conf.awsgateway_compatible then
upstream_body = aws_serializer(ctx, conf)
elseif conf.forward_request_body or
conf.forward_request_headers or
conf.forward_request_method or
conf.forward_request_uri then
if conf.forward_request_method then
upstream_body.request_method = kong.request.get_method()
end
if conf.forward_request_headers then
upstream_body.request_headers = kong.request.get_headers()
end
if conf.forward_request_uri then
upstream_body.request_uri = kong.request.get_path_with_query()
upstream_body.request_uri_args = kong.request.get_query()
end
if conf.forward_request_body then
local content_type = kong.request.get_header("content-type")
local body_raw = request_util.read_request_body(conf.skip_large_bodies)
local body_args, err = kong.request.get_body()
if err and err:match("content type") then
body_args = {}
if not raw_content_types[content_type] and conf.base64_encode_body then
body_raw = ngx_encode_base64(body_raw)
upstream_body.request_body_base64 = true
end
end
upstream_body.request_body = body_raw
upstream_body.request_body_args = body_args
end
else
local body_args = kong.request.get_body()
upstream_body = kong.table.merge(kong.request.get_query(), body_args)
end
local upstream_body_json, err = cjson.encode(upstream_body)
if not upstream_body_json then
kong.log.err("could not JSON encode upstream body",
" to forward request values: ", err)
end
local region = conf.aws_region or AWS_REGION
local host = conf.host
if not region then
return error("no region specified")
end
if not host then
host = fmt("lambda.%s.amazonaws.com", region)
end
local path = fmt("/2015-03-31/functions/%s/invocations", conf.function_name)
local port = conf.port or AWS_PORT
local opts = {
region = region,
service = "lambda",
method = "POST",
headers = {
["X-Amz-Target"] = "invoke",
["X-Amz-Invocation-Type"] = conf.invocation_type,
["X-Amz-Log-Type"] = conf.log_type,
["Content-Type"] = "application/x-amz-json-1.1",
["Content-Length"] = upstream_body_json and tostring(#upstream_body_json),
},
body = upstream_body_json,
path = path,
host = host,
port = port,
query = conf.qualifier and "Qualifier=" .. conf.qualifier
}
local aws_conf = {
aws_region = conf.aws_region,
aws_assume_role_arn = conf.aws_assume_role_arn,
aws_role_session_name = conf.aws_role_session_name,
}
if not conf.aws_key then
local iam_role_cred_cache_key = fmt(IAM_CREDENTIALS_CACHE_KEY_PATTERN, conf.aws_assume_role_arn or "default")
local iam_role_credentials = kong.cache:get(
iam_role_cred_cache_key,
nil,
fetch_aws_credentials,
aws_conf
)
if not iam_role_credentials then
return kong.response.error(500)
end
opts.access_key = iam_role_credentials.access_key
opts.secret_key = iam_role_credentials.secret_key
opts.headers["X-Amz-Security-Token"] = iam_role_credentials.session_token
else
opts.access_key = conf.aws_key
opts.secret_key = conf.aws_secret
end
local request
request, err = aws_v4(opts)
if err then
return error(err)
end
local uri = port and fmt("https://%s:%d", host, port)
or fmt("https://%s", host)
local proxy_opts
if conf.proxy_url then
proxy_opts = { https_proxy = conf.proxy_url }
end
local client = http.new()
client:set_timeout(conf.timeout)
local kong_wait_time_start = get_now()
local res, err = client:request_uri(uri, {
method = "POST",
path = request.url,
body = request.body,
headers = request.headers,
ssl_verify = false,
proxy_opts = proxy_opts,
keepalive_timeout = conf.keepalive,
})
if not res then
return error(err)
end
local content = res.body
if res.status >= 400 then
return error(content)
end
ctx.KONG_WAITING_TIME = get_now() - kong_wait_time_start
local headers = res.headers
if ngx_var.http2 then
headers["Connection"] = nil
headers["Keep-Alive"] = nil
headers["Proxy-Connection"] = nil
headers["Upgrade"] = nil
headers["Transfer-Encoding"] = nil
end
local status
if conf.is_proxy_integration then
local proxy_response, err = extract_proxy_response(content)
if not proxy_response then
kong.log.err(err)
return kong.response.exit(502, { message = "Bad Gateway",
error = "could not JSON decode Lambda " ..
"function response: " .. err })
end
status = proxy_response.status_code
headers = kong.table.merge(headers, proxy_response.headers)
content = proxy_response.body
end
if not status then
if conf.unhandled_status
and headers["X-Amz-Function-Error"] == "Unhandled"
then
status = conf.unhandled_status
else
status = res.status
end
end
headers = kong.table.merge(headers)
if kong.configuration.enabled_headers[VIA_HEADER] then
headers[VIA_HEADER] = VIA_HEADER_VALUE
end
return kong.response.exit(status, content, headers)
end