无法使用 Amazon Amplify 从 Lambda 调用 GraphQL

Posted

技术标签:

【中文标题】无法使用 Amazon Amplify 从 Lambda 调用 GraphQL【英文标题】:Failing to call GraphQL from Lambda using Amazon Amplify 【发布时间】:2021-03-26 16:44:59 【问题描述】:

我正在使用 Amazon Amplify 创建一个访问 AppSync GraphQL 终端节点内容的函数。 使用命令行我创建了新函数和 API,我可以从我的前端应用程序中正确调用它,但是,我不断收到此错误:

2020-12-16T01:39:40.524Z    979abb8d-4d64-4929-937a-03b0cb495174    INFO    error posting to appsync:  Error: Request failed with status code 401
    at createError (/var/task/node_modules/axios/lib/core/createError.js:16:15)
    at settle (/var/task/node_modules/axios/lib/core/settle.js:17:12)
    at IncomingMessage.handleStreamEnd (/var/task/node_modules/axios/lib/adapters/http.js:244:11)
    at IncomingMessage.emit (events.js:326:22)
    at endReadableNT (_stream_readable.js:1223:12)
    at processTicksAndRejections (internal/process/task_queues.js:84:21) 
  config: 
    url: 'https://y63v24inqneirizeuiig7x5g54.appsync-api.us-east-1.amazonaws.com/graphql',
    method: 'post',
    data: '"query":"query listCompetitions \\n  listCompetitions \\n    items \\n      createdAt\\n      id\\n      likes\\n      updatedAt\\n      votes\\n      websiteImageKey\\n      websiteUrl\\n      user \\n        username\\n        imageKey\\n      \\n      websiteDescription\\n    \\n  \\n\\n"',
    headers: 
      Accept: 'application/json, text/plain, */*',
      'Content-Type': 'application/json;charset=utf-8',
      'x-api-key': '7aeiasrvb5bczhmlt2nnbpfuyi',
      'User-Agent': 'axios/0.21.0',
      'Content-Length': 284
    ,

我用来从我的函数中调用 GraphQL 的代码是来自 link。

const graphqlData = await axios(
      url: process.env.API_MAINDATA_GRAPHQLAPIENDPOINTOUTPUT,
      method: "post",
      headers: 
        "x-api-key": process.env.API_MAINDATA_GRAPHQLAPIIDOUTPUT,
      ,
      data: 
        query: print(listCompetition),
      ,
    );

Amplify 将 URL 和 KEY 添加到 env 中,我已经为相关 API 添加了 API_KEY 身份验证,所以我不明白为什么我仍然得到401 error

我注意到的一件事是文档说要使用:

'x-api-key': process.env.API_<YOUR_API_NAME>_GRAPHQLAPIKEYOUTPUT

但是_GRAPHQLAPIKEYOUTPUT 没有生成,所以我改用_GRAPHQLAPIIDOUTPUT,不确定这是否发生了变化,或者我是否缺少环境常量。

【问题讨论】:

A 401 错误是由于您没有正确的授权。需要_GRAPHQLAPIKEYOUTPUT 才能访问x-api-key @yudhiesh 是的,奇怪的是我的 lambda .env 上没有密钥,有什么想法可以强制它重新创建吗? 【参考方案1】:

您是否正确签署了您的请求?如果您还没有,请查看AWS.Signers.V4。

我遇到了和你类似的问题,我最终实现了一个专用的 Lambda 函数来执行 GraphQL 操作。这样一来,只要我想执行 GraphQL 操作,我就可以调用我的 Lambda 函数。

类似:

/* Amplify Params - DO NOT EDIT
    API_XXXXXX_GRAPHQLAPIENDPOINTOUTPUT
    API_XXXXXX_GRAPHQLAPIIDOUTPUT
    ENV
    REGION
Amplify Params - DO NOT EDIT */

const AWS = require('aws-sdk')
const https = require('https')
const urlParse = require('url').URL

const APPSYNC_URL = process.env['API_XXXXXX_GRAPHQLAPIENDPOINTOUTPUT']
const REGION = process.env['REGION']

const ENDPOINT = new urlParse(APPSYNC_URL).hostname.toString()

//
// execute a graphql operation via appsync
//
exports.handler = async ( item, operation, operationName ) => 
  const request = createSignedRequest(
    ENDPOINT,
    item,
    operation,
    operationName,
    REGION,
    APPSYNC_URL,
  )
  return getResponseFromApi(ENDPOINT, request)


//
// create a signed graphql operation request
//
const createSignedRequest = (
  endpoint,
  item,
  operation,
  operationName,
  region,
  url,
) => 
  const request = new AWS.HttpRequest(url, region)
  request.method = 'POST'
  request.path = '/graphql'
  request.headers.host = endpoint
  request.headers['Content-Type'] = 'application/json'
  request.body = JSON.stringify(
    query: operation,
    operationName: operationName,
    variables: item,
  )

  const signer = new AWS.Signers.V4(request, 'appsync', true)
  signer.addAuthorization(AWS.config.credentials, AWS.util.date.getDate())

  return request


//
// send a request to the appsync api and return the response data
//
const getResponseFromApi = (endpoint, request) => 
  return new Promise((resolve, reject) => 
    const httpRequest = https.request(
       ...request, host: endpoint ,
      (result) => 
        result.on('data', (data) => 
          resolve(JSON.parse(data.toString()))
        )
      ,
    )
    httpRequest.write(request.body)
    httpRequest.end()
  )

【讨论】:

以上是关于无法使用 Amazon Amplify 从 Lambda 调用 GraphQL的主要内容,如果未能解决你的问题,请参考以下文章

如何在没有 Amplify 的情况下使用 Amazon Cognito

AWS Amplify 和 amazon-cognito-identity-js 的区别?

使用 Amazon Amplify快速创建简单的 Android 应用程序

基于 Amazon Amplify 构建自己的首个 iOS 应用程序

基于 Amazon Amplify 构建自己的首个 iOS 应用程序

基于 Amazon Amplify 构建自己的首个 iOS 应用程序