function AWSLambdaHandler:access()

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